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++不同是单继承,但是可以继承多接口.完全面向 ...
随机推荐
- iframe框架默认占满整个屏幕
<script language="JavaScript"> if (window != top) { top.location.href = location.hre ...
- MongoDB学习笔记02
MongoDB中使用find来进行查询,查询就是返回一个集合中文档的子集,子集合的范围从0个文档到整个集合.find的第一个参数决定了要返回哪些文档.空的查询文档{}会匹配集合的全部内容,要是不指定查 ...
- textView富文本点击事件
NSDictionary * attDic = [NSDictionary dictionaryWithObjectsAndKeys:RGBCOLOR(31, 132, 204),NSForegrou ...
- 使用 Require.js 引用第三方框架时遇到的一些情况
使用 Require.js 引用第三方框架时遇到的一些情况 在使用Require.js解析依赖的时候,会出现以下几种情况: 程序中的依赖关系 当前程序 依赖于 B包, B包 依赖于 A包 A包与B包两 ...
- UVA 719 / POJ 1509 Glass Beads (最小表示法/后缀自动机)
题目大意: 给出一个长度为N的字符串,求其字典序最小的循环同构. N<=10W. 算法讨论: 算法一.最小表示法.定义题. 算法二.后缀自动机. Codes: #include <iost ...
- codeforces 337C Quiz(贪心)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Quiz Manao is taking part in a quiz. The ...
- (原)ubuntu14手动安装matplotlib1.5
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5681059.html 参考网址: http://matplotlib.org/users/instal ...
- (原)Ubuntu16中使用nvidia官方提供的驱动,而非自带的驱动
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5638185.html 安装完ubuntu16后,显卡显示的是Gallium... 在“设置-软件和更新 ...
- js 日期天数相加减,格式化yyyy-MM-dd
参数格式: date :2016-03-02 days:-3(2)当为负数的时候日期往前推,为正数,日期往后推 function addDate(date, days) { var d = new D ...
- 关于《Cocos2d-x建工程时避免copy文件夹和库》的更新
在前几篇博文中大概了解了Cocos2d-x引擎的基本结构后打算开始实际操作,便在网上转载了一篇关于VS新建Cocos2d-x项目的文章.今天实际操作的时候发现博主使用的引擎版本和我的不一致(<C ...