Java核心技术,让计算机"一芯多用"的多线程技术
我们在使用计算的时候会感受到计算机好像在同时执行很多任务,这也是我最初接触计算机给我留下的印象,而我们普通人在同一时刻大脑只能思考一件事情(当然不排除一些异能者能够做到一心二用),而且我们在思考完一件事情之后进入另一件事情的思考需要花费一段时间适应。而对于计算机来说,其执行任务间的切换是相当快的,以前计算机还是单CPU的时候就是通过这种在各种任务之间的快速切换而“伪实现”了同时执行任务。随着硬件飞速发展,计算机配备了多CPU芯片,就在真正意义上实现了多线程,实现了同时执行多种任务。
代号为“Prodigy”的64位多核、多线程处理器
然而万事万物都是有利有弊,多线程在为应用带来性能提高的同时,也带来了新的问题。因为多线程共享内存变量/对象,且可以同时修改同一个内存变量/对象,那么就可以产生访问冲突,从而造成数据不一致,这就是所谓的线程安全性问题。因线程安全处理不当造成的程序错误,其错误现象经常表现得比较随机不可确定,难以发现规律。因此,在Debug时很有挑战性。先前在《线程的六个状态以及其安全性问题的个例解析》《程序设计中如何避免死锁问题的发生?》在学习多线程的时候,除了理解线程运行原理或者机制和线程管理的基本方法外,如果保证线程安全也是多线程的一种重点。
下面我通过一个单线程的程序和改进之后的多线程程序用图形界面的方式将单线程与多线程的区别简单展示一下
注意: 将Ball.java; BallComponent.java; Bounce.java; BounceThread.java四个Java文件放置在同一文件目录下,全部编译之后,分别运行Bounce.java和BounceThread.java即可观察到效果。
强烈建议各位朋友们玩一下,尤其是对多线程的概念比较模糊的朋友们,比较Bounce和BounceThread的区别,对理解和认识多线程会起到一定的帮助。
Ball.java
import java.awt.geom.*; public class Ball { private static final int XSIZE = 15;
private static final int YSIZE = 15;
private double x = 0;
private double y = 0;
private double dx = 1;
private double dy = 1; public void move(Rectangle2D bounds) {
x += dx;
y += dy;
if(x < bounds.getMinX()) {
x = bounds.getMinX();
dx = -dx;
}
if(x + XSIZE >= bounds.getMaxX()) {
x = bounds.getMaxX() - XSIZE;
dx = -dx;
}
if(y < bounds.getMinY()) {
y = bounds.getMinY();
dy = -dy;
}
if(y + YSIZE >= bounds.getMaxY()) {
y = bounds.getMaxY() - YSIZE;
dy = -dy;
}
} public Ellipse2D getShape() {
return new Ellipse2D.Double(x, y, XSIZE, YSIZE);
} }
BallComponent.java
import java.awt.*;
import java.util.*;
import javax.swing.*; public class BallComponent extends JPanel {
private ArrayList<Ball> balls = new ArrayList<Ball>(); public void add(Ball b) {
balls.add(b);
} public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for(Ball b : balls) {
g2.fill(b.getShape());
}
}
}
Bounce.java 单线程程序
import java.awt.*;
import java.awt.event.*;
import javax.swing.*; /**
* 实现功能: 创建一个用户界面, 点击按钮start产生一个小黑球做直线弹射运动, 直至某点停止运动
其中按一次start按钮需要等到小黑球停止运动的时候才可以再按一次
*/
public class Bounce {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new BounceJFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
} class BounceJFrame extends JFrame { public static final int DEFAULT_WIDTH = 450;
public static final int DEFAULT_HEIGHT = 350;
public static final int STEPS = 1000;
public static final int DELAY = 3;
private BallComponent comp; public BounceJFrame() {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
setTitle("Bounce"); comp = new BallComponent();
add(comp, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
addButton(buttonPanel, "Start", new ActionListener() {
public void actionPerformed(ActionEvent event) {
addBall();
}
}); addButton(buttonPanel, "Close", new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
add(buttonPanel, BorderLayout.SOUTH);
} public void addButton(Container c, String title, ActionListener listener) {
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
} public void addBall() {
try {
Ball ball = new Ball();
comp.add(ball); for(int i = 1; i <= STEPS; i++) {
ball.move(comp.getBounds());
comp.paint(comp.getGraphics());
Thread.sleep(DELAY);
}
} catch(InterruptedException e) {}
}
}
BounceThread.java 多线程程序
import java.awt.*;
import java.awt.event.*;
import javax.swing.*; /*
* 实现功能: 与Bounce.java不同的是, 这个程序按下start按钮创建一个小黑球运动之后可以立即再次按下按钮创建一个小黑球
*
*/
public class BounceThread {
public static void main(String[] args0) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new BounceJFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
} class BallRunnable implements Runnable {
private Ball ball;
private Component component;
public static final int STEPS = 1000;
public static final int DELAY = 5; public BallRunnable(Ball aBall, Component aComponent) {
ball = aBall;
component = aComponent;
} public void run() {
try {
for(int i = 1; i <= STEPS; i++) {
ball.move(component.getBounds());
component.repaint();
Thread.sleep(DELAY);
}
} catch(InterruptedException e) {}
} } class BounceJFrame extends JFrame {
private BallComponent comp;
public static final int DEFAULT_WIDTH = 450;
public static final int DEFAULT_HEIGHT = 350;
public static final int STEPS = 1000;
public static final int DELAY = 3; public BounceJFrame() {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
setTitle("BounceThread"); comp = new BallComponent();
add(comp, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
addButton(buttonPanel, "Start", new ActionListener() {
public void actionPerformed(ActionEvent event) {
addBall();
}
}); addButton(buttonPanel, "Close", new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
add(buttonPanel, BorderLayout.SOUTH);
} /*
*
*
*/ public void addButton(Container c, String title, ActionListener listener) {
JButton button = new JButton(title);
c.add(button);
button.addActionListener(listener);
} public void addBall() {
Ball ball = new Ball();
comp.add(ball);
Runnable r = new BallRunnable(ball, comp);
Thread t = new Thread(r);
t.start();
}
}
下图是两个程序各自的运行截图,其中左图为单线程 右图为多线程
通过简单观察可以看到左右两图之间的区别,左图中只有小黑球到达终点时,按钮才回弹回来,这就是单线程。
多线程作为Java的核心内容之一,作为程序性能提升的基本途径。想要充分调用计算资源,我们还需要在编程的时候避免过于复杂的设计,特别是对于初学者而言,学习多线程就好像进入了一个全新的领域,通过学习多线程的思维方式,对我们思维的扩展还是有一定好处的。
Java核心技术,让计算机"一芯多用"的多线程技术的更多相关文章
- Java核心技术卷一基础知识-第14章-多线程-读书笔记
第 14 章 多线程 本章内容: * 什么是线程 * 中断线程 * 线程状态 * 线程属性 * 同步 * 阻塞队列 * 线程安全的集合 * Collable与Future * 执行器 * 同步器 * ...
- 《Java核心技术 卷II 高级特性(原书第9版)》
<Java核心技术 卷II 高级特性(原书第9版)> 基本信息 原书名:Core Java Volume II—Advanced Features(Ninth Edition) 作者: ( ...
- Java核心技术点之多线程
学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java! 本文主要从整体上介绍Java中的多线程技术, ...
- Java核心技术点之泛型
1. Why ——引入泛型机制的原因 假如我们想要实现一个String数组,并且要求它可以动态改变大小,这时我们都会想到用ArrayList来聚合String对象.然而,过了一阵,我们想要实现一个大小 ...
- Java核心技术点之集合框架
1. 概述 Java集合框架由Java类库的一系列接口.抽象类以及具体实现类组成.我们这里所说的集合就是把一组对象组织到一起,然后再根据不同的需求操纵这些数据.集合类型就是容纳这些对象的一个容 ...
- Java核心技术点之内部类
1. 为什么要使用内部类 内部类就是定义在一个类内部的类,那么为什么要使用内部类呢?主要原因有以下几点:第一,内部类中定义的方法能访问到它所在外部类的私有属性及方法:第二,外部类无法实现对同一 ...
- Java核心技术点之动态代理
本篇博文会从代理的概念出发,介绍Java中动态代理技术的使用,并进一步探索它的实现原理.由于个人水平有限,叙述中难免出现不清晰或是不准确的地方,希望大家可以指正,谢谢大家:) 一.概述 1. 什么是代 ...
- 读《java核心技术卷一》有感
过去一个多月了吧.才囫囵吞枣地把这书过了一遍.话说这书也够长的,一共706页.我从来不是个喜欢记录的人,一直以来看什么书都是看完了就扔一边去,可能有时候有那么一点想记录下来的冲动,但算算时间太紧,很多 ...
- java核心技术学习笔记之一程序设计概述
Java 核心技术之一程序设计概述 一. Java语言的特点 简单行 :取经于C++,排除了C++不常用的指针.结构等,增加垃圾回收. 面向对象:与C++不同是单继承,但是可以继承多接口.完全面向 ...
随机推荐
- [j2ee][IDEA properties中文乱码解决]
http://my.oschina.net/pengzai/blog/133908 在project settings - File Encoding,在标红的选项上打上勾,确定即可
- html_day4+css
表单控件共有的属性: enabled:表示表单控件可用 disabled:表示表单控件被禁用 readonly:表示表单控件只能读name属性值的作用: 需要将表单的数据提交到服务器处理就要写name ...
- 本地计算机上的OracleOraDb11g_home2TNSListener服务启动又停止了。
电脑上装了oracle后启动很慢,然后我就不oracle服务设置成手动启动,没想到今天启动的时候居然报错 折腾了一上午,终于搞定, 在环境变量中把ORACLE_HOME 设置成D:\app\XL\pr ...
- iOS 面试题 1
1. 简述OC中内存管理机制.与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?readwrite ...
- Struts2之Action基础与配置
Action基础 Action是什么 在Struts2中,一个Action类代表一次请求或调用,每个请求的动作都对应于一个相应的Action类,一个Action类是一个独立的工作单元.也就是,用户的每 ...
- UVA 10253 Series-Parallel Networks (树形dp)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Series-Parallel Networks Input: standard ...
- UVALive 4123 Glenbow Museum (组合数学)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud 易得,当n为奇数或者n<3时,答案为0,否则该序列中必定有(n+4)/2个R ...
- Struts1.x下使用jquery的Ajax获取后台数据
jquery中有多种Ajax方法来获取后台数据,我使用的是$.get()方法,具体的理论我不解释太多,要解释也是从别的地方copy过来的.下面就介绍我的项目中的实现方法. 前台页面: ...
- js验证身份证格式
(function(){ Validate={ data:{ // 加权因子 Wi : [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 ...
- vi打开二进制文件
vi -b filename <c7><cc>><0b><00><00><01><01><c2>& ...