我们在使用计算的时候会感受到计算机好像在同时执行很多任务,这也是我最初接触计算机给我留下的印象,而我们普通人在同一时刻大脑只能思考一件事情(当然不排除一些异能者能够做到一心二用),而且我们在思考完一件事情之后进入另一件事情的思考需要花费一段时间适应。而对于计算机来说,其执行任务间的切换是相当快的,以前计算机还是单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核心技术,让计算机"一芯多用"的多线程技术的更多相关文章

  1. Java核心技术卷一基础知识-第14章-多线程-读书笔记

    第 14 章 多线程 本章内容: * 什么是线程 * 中断线程 * 线程状态 * 线程属性 * 同步 * 阻塞队列 * 线程安全的集合 * Collable与Future * 执行器 * 同步器 * ...

  2. 《Java核心技术 卷II 高级特性(原书第9版)》

    <Java核心技术 卷II 高级特性(原书第9版)> 基本信息 原书名:Core Java Volume II—Advanced Features(Ninth Edition) 作者: ( ...

  3. Java核心技术点之多线程

    学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java! 本文主要从整体上介绍Java中的多线程技术, ...

  4. Java核心技术点之泛型

    1. Why ——引入泛型机制的原因 假如我们想要实现一个String数组,并且要求它可以动态改变大小,这时我们都会想到用ArrayList来聚合String对象.然而,过了一阵,我们想要实现一个大小 ...

  5. Java核心技术点之集合框架

    1. 概述     Java集合框架由Java类库的一系列接口.抽象类以及具体实现类组成.我们这里所说的集合就是把一组对象组织到一起,然后再根据不同的需求操纵这些数据.集合类型就是容纳这些对象的一个容 ...

  6. Java核心技术点之内部类

    1. 为什么要使用内部类     内部类就是定义在一个类内部的类,那么为什么要使用内部类呢?主要原因有以下几点:第一,内部类中定义的方法能访问到它所在外部类的私有属性及方法:第二,外部类无法实现对同一 ...

  7. Java核心技术点之动态代理

    本篇博文会从代理的概念出发,介绍Java中动态代理技术的使用,并进一步探索它的实现原理.由于个人水平有限,叙述中难免出现不清晰或是不准确的地方,希望大家可以指正,谢谢大家:) 一.概述 1. 什么是代 ...

  8. 读《java核心技术卷一》有感

    过去一个多月了吧.才囫囵吞枣地把这书过了一遍.话说这书也够长的,一共706页.我从来不是个喜欢记录的人,一直以来看什么书都是看完了就扔一边去,可能有时候有那么一点想记录下来的冲动,但算算时间太紧,很多 ...

  9. java核心技术学习笔记之一程序设计概述

    Java 核心技术之一程序设计概述 一.   Java语言的特点 简单行 :取经于C++,排除了C++不常用的指针.结构等,增加垃圾回收. 面向对象:与C++不同是单继承,但是可以继承多接口.完全面向 ...

随机推荐

  1. Zookeeper学习记录(一):设计与实现

    概述 Zookeeper是一个分布式的.开源的分布式应用协调服务.它暴露了一组简单的基础原件,分布式应用可以在这些原件之上实现更高级别的服务,如同步.配置维护.群组.和命名.它被设计成容易编程实现的, ...

  2. wifi_uplink脚本分析

    ~ >: vim apps/tools/wifi_uplink  #!/bin/sh # Copyright (C) 2012 GuoWenxue <guowenxue@gmail.com ...

  3. web项目的两个创建形式website和webapplication

    前言 在利用VS2010创建web项目的时候,会有两个选择.可以选择直接创建website网站,还可以选择使用 webapplication应用程序.刚刚接触web开发,看到这两个就疑惑了,既然是都可 ...

  4. markdown 书写代码

    近期基于github + hexo 搭建了自己的博客.開始用markdown写博客,推荐 mac 平台用 mou 这个软件或者 vim. 介绍下markdown语法插入代码的规则: 有一种方法是全部代 ...

  5. 跟我学系列教程——《13天让你学会Redis》火热报名中

    学习目标 每天2小时,13天让你学会Redis. 本课程针对Redis新手,甚至连Redis是什么都没有听说过的同学.课程会具体介绍Redis是什么以及为什么要使用Redis,结合项目实践旨在让学生从 ...

  6. thinkphp框架的路径问题 - 总结

    thinkphp框架的路径问题 - 总结 (2011-06-21 11:01:28) 转载▼ 标签: thinkphp 框架 路径 杂谈 分类: Php TP中有不少路径的便捷使用方法,比如模板中使用 ...

  7. Android中获取apk基本信息

    一 PackageManager可以获得的所有包节点信息: 1,所有节点的基类:PackageItemInfo: 2,PackageInfo:package的全面信息,与AndroidManifest ...

  8. 疯狂安卓Android自学笔记

    开发者必备自学工具: 谷歌搜索:www.yundou.info Android原版开发文档 (英文) Doc http://www.phoned.cn/docs/reference/android/v ...

  9. 层层递进Struts1(六)自定义转换器

    Struts提供的类型转换有限,如果我们强行使用没有的类型转换,则会出现错误,以Date类型为例: org.apache.catalina.core.StandardWrapperValve invo ...

  10. 修改mysql编码为UTF-8

    mysql> show variables like '%character%'; +--------------------------+--------------------------- ...