读Java编程艺术之笔记(多线程)(一)

Java多线程的目的是最大限度的利用CPU资源,实际上,操作系统的多进程实现了多任务的并发执行,程序的多线程实现了进程的并发执行。其前提是操作系统对多任务、多进程、多线程的支持。另外,在JVM的线程调度部分采用抢占式调度机制。
下面是一个简单的多线程的例子
public class SimpleThreadTest { public static void main(String[] args){ System.out.println(Thread.currentThread().getName()); new HelloThread().start(); Thread letter = new Thread(new EnglishWord()); Thread word = new Thread(new ChineseWord()); letter.start(); word.start(); } } class HelloThread extends Thread { public void run(){ System.out.println("Hello world! "+this.getName()+" is running "); } } class Letter { public void delay(){ long n = (long)(Math.random()*100000); for(int i =0; i<n; i++){ System.out.print(""); } } public void display(String letter){ System.out.print(letter); } } class EnglishWord extends Letter implements Runnable{ public void run(){ display("Java "); delay(); display("SE "); } } class ChineseWord extends Letter implements Runnable{ public void run(){ display("爪哇 "); delay(); display("标准版本 "); } }
运行结果:
D:\Users\xhj>java SimpleThreadTest
main
Hello world! Thread-0 is running
Java 爪哇 SE 标准版本
D:\Users\xhj>java SimpleThreadTest
main
Hello world! Thread-0 is running
Java 爪哇 标准版本 SE
从上例可以看出主方法main()是运行在名为main的线程中即主线程,然后我们一步一步介绍Java多线程:
1. 建立线程(该部分参考http://lavasoft.blog.51cto.com/62575/99151)
使用java.lang.Thread类或者java.lang.Runnable接口编写代码来定义、实例化和启动新线程。在上例中可看到两种情况的实现。
线程总体分两类:用户线程和守候线程。守候线程专为后台服务,此类线程无需显示关闭,当所有线程运行结束,守候线程自动关闭,有线程在执行,守候线程就不会关闭。
在线程的Thread对象上调用start()方法,而不是run()或者别的方法。在调用start()方法之前:线程处于新状态中,新状态指有一个Thread对象,但还没有一个真正的线程。
在调用start()方法之后发生了一系列复杂的事情:
2.3 sleep()
sleep()方法可以是当前运行线程在指定毫秒时间处于暂停运行状态。当这个时间超时后,线程调度器将其设置为可执行状态。sleep()方法抛出InterruptedException,属检查性异常,必须提供异常处理机制才可运行。
2.4 join()
join()方法实际上使调用它的线程插入运行,阻塞当前线程的执行,直到调用它的线程执行完毕,才恢复被阻塞线程的运行。如果调用它的线程是无限循环,其他线程则得不到执行。但如果其他线程中断它的运行,则会抛出异常InterruptedException,而停止继续运行。
public class JoinExample { public static void main(String[] args){ Thread demoPI = new Thread(new Estimate()); demoPI.start(); try { demoPI.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("PI = "+Estimate.PI); } } class Estimate implements Runnable{ public static double PI = 0.0; private int sign = 1; @Override public void run() { // TODO Auto-generated method stub for (long i = 1; i <= 9999999; i += 2) { PI += 4.0*(double)sign/i; sign = -sign; } } }
运行结果:
PI = 3.1415924535897797
若取消 demo.join();则运行结果为:
PI = 0.0
2.5 interrupt()
interrupt()用来中断当前正在运行的线程。当一个线程被中断后,将抛出InterruptedException,其isInterrupted()的中断状态也将设置为真。注意,interrupt()并不中断线程的运行,但抛出中断异常并设置中断状态为真,可通过isInterrupted()检查中断状态。
import java.util.Scanner; public class InterruptExample { public static void main(String[] args){ Thread service = new Service(); service.setName("Enthusiasm"); service.start(); Scanner sc = new Scanner(System.in); String command = ""; while (!command.equals("interrupt")) { command = sc.next(); } service.interrupt(); } } class Service extends Thread { @Override public void run() { // TODO Auto-generated method stub while (!this.isInterrupted()) { System.out.println(this.getName()+" is providing service ..."); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block //e.printStackTrace(); break; } } System.out.println("Service is interrupted ..."); } }
运行结果:
Enthusiasm is providing service ...
Enthusiasm is providing service ...
inEnthusiasm is providing service ...
terruptEnthusiasm is providing service ...
Service is interrupted ...
下面是一个小例子,利用多线程从一个二维数组中找出最大数
public class FindMaxExample { private static final int ROW = 100, COL = 200; public static long startTime, endTime; public static void main(String[] args) { MaxThread[] eachMaxThreads = new MaxThread[ROW]; double[][] matrix = Matrix.generator(ROW, COL); double max = Double.MIN_VALUE; for (int i = 0; i < eachMaxThreads.length; i++) { eachMaxThreads[i] = new MaxThread(matrix[i]); eachMaxThreads[i].start(); } startTime = System.currentTimeMillis(); System.out.println("start time: "+startTime); try { for (int i = 0; i < eachMaxThreads.length; i++) { eachMaxThreads[i].join(); max = Math.max(max, eachMaxThreads[i].getMax()); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } endTime = System.currentTimeMillis(); System.out.println("end time: "+endTime); System.out.println("Max of the matrix is: "+max); System.out.println("Completion time: "+(endTime-startTime)+" ms."); } } class MaxThread extends Thread { private double max = Double.MIN_VALUE; private double[] eachArray; public MaxThread(double[] eachArray) { this.eachArray = eachArray; } public void run() { for (int i = 0; i < eachArray.length; i++) { max = Math.max(max, eachArray[i]); } } public double getMax() { return max; } } class Matrix { public static double[][] generator(int row, int col) { double[][] matrix = new double[row][col]; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { matrix[i][j] = Math.random() * 101; } } return matrix; } }
运行结果:
start time: 1365560078085 end time: 1365560078085 Max of the matrix is: 100.99740370977023 Completion time: 0 ms.
大家可以试一下,用单线程来完成同样工作所需的时间。
浙公网安备 33010602011771号