Java入门——多线程(一)
进程与线程的区别
进程是程序的一次动态的执行的过程,需要经历从代码的加载,代码执行到执行完毕的一个完整过程,这个过程也是进程重产生,发展到最终消亡的过程。多进程操作系统利用CPU的分时机制,分时段执行不同程序,由于CPU运行速度非常快,所以就想是多个进程同时运行一样。
线程是比进程更小的执行单位,线程在进程的基础之上进行的进一步划分。所谓多线程是指在一个进程在执行过程中可以产生多个更小的程序单元,这些更小的单元成为线程,可以同时存在,同时运行。
所谓的线程是程序的运行流程,多线程就是指可以同时运行多个程序块(Java语言支持多线程)。
线程的实现
主要有两种手段,第一是继承Thread类,第二个是实现Runable接口。
继承Thread类
Thread类是java.lang包中定义的,一个类只要继承了Thread类,此类就称为多线程实现类。在Thread子类中,必须覆写run()方法,此方法为线程的主体,线程类的定义如下:
1 package Sep18; 2 /* 3 * 线程类的格式 4 * class 类名称 extends Thread{ 5 * 属性------; 6 * 方法------; 7 * public void run(){ 8 * 线程主体; 9 * } 10 * } 11 */ 12 public class ThreadDemo01 { 13 public static void main(String args[]){ 14 MyThread mt1=new MyThread("线程A"); 15 MyThread mt2=new MyThread("线程B"); 16 17 mt1.start();//启动多线程 18 mt2.start();//启动多线程 19 20 } 21 } 22 class MyThread extends Thread{ 23 private String name; 24 public MyThread(String name){ 25 this.name=name; 26 } 27 public void run(){ 28 for (int i=0;i<10;i++){ 29 System.out.println(name+"运行,i="+i); 30 } 31 } 32 }
线程A运行,i=0 线程A运行,i=1 线程A运行,i=2 线程A运行,i=3 线程A运行,i=4 线程B运行,i=0 线程B运行,i=1 线程A运行,i=5 线程A运行,i=6 线程A运行,i=7 线程A运行,i=8 线程B运行,i=2 线程A运行,i=9 线程B运行,i=3 线程B运行,i=4 线程B运行,i=5 线程B运行,i=6 线程B运行,i=7 线程B运行,i=8 线程B运行,i=9
如果一个类通过继承Thread方法实现多线程,那么只能调用一次start()方法,否者会出现异常。
实现Runnable接口
Runnable接口只定义了一个抽象方法:public void run();
/* 3 * 线程类的格式 4 * class 类名称 implements Thread{ 5 * 属性------; 6 * 方法------; 7 * public void run(){ 8 * 线程主体; 9 * } 10 * } 11 */
1 package Sep18; 12 public class ThreadDemo02 { 13 public static void main(String args[]){ 14 MyThread2 mt1=new MyThread2("线程A"); 15 MyThread2 mt2=new MyThread2("线程B"); 16 Thread t1=new Thread(mt1); 17 Thread t2=new Thread(mt2); 18 t1.start();//启动多线程 19 t2.start();//启动多线程 20 21 } 22 } 23 class MyThread2 implements Runnable{ 24 private String name; 25 public MyThread2(String name){ 26 this.name=name; 27 } 28 public void run(){ 29 for (int i=0;i<10;i++){ 30 System.out.println(name+"运行,i="+i); 31 } 32 } 33 }
线程A运行,i=0 线程A运行,i=1 线程B运行,i=0 线程A运行,i=2 线程B运行,i=1 线程A运行,i=3 线程B运行,i=2 线程A运行,i=4 线程B运行,i=3 线程A运行,i=5 线程B运行,i=4 线程A运行,i=6 线程B运行,i=5 线程A运行,i=7 线程B运行,i=6 线程A运行,i=8 线程B运行,i=7 线程A运行,i=9 线程B运行,i=8 线程B运行,i=9
实际上实现Runnable接口后,开始线程还是利用的Thread的两个构造方法: public Thread(Runnable target);和public Thread (Runnable target , String name);这两个构造函数都接受Runnable接口的子类实例对象。
用Runnable接口实现多线程的优势
首先第一点:避免Java单继承带来的限制。
然后:增强程序的健壮性,代码能够被对个线程共享,代码与数据是独立的。适合多个相同程序代码处理同一资源的情况。
看下面例子理解第二点:
使用继承Thread类:
1 package Sep18; 2 3 public class ThreadDemo03 { 4 public static void main(String args[]){ 5 MyThread02 mt01=new MyThread02(); 6 MyThread02 mt02=new MyThread02(); 7 MyThread02 mt03=new MyThread02(); 8 mt01.start(); 9 mt02.start(); 10 mt03.start(); 11 } 12 } 13 class MyThread02 extends Thread{ 14 private int ticket=5; 15 public void run(){ 16 for (int i=0;i<=12;i++){ 17 if (ticket>0){ 18 System.out.println("卖一张票,剩余:"+ticket+"张"); 19 ticket--; 20 } 21 } 22 } 23 }
卖一张票,剩余:5张 卖一张票,剩余:4张 卖一张票,剩余:5张 卖一张票,剩余:5张 卖一张票,剩余:4张 卖一张票,剩余:3张 卖一张票,剩余:2张 卖一张票,剩余:1张 卖一张票,剩余:3张 卖一张票,剩余:2张 卖一张票,剩余:4张 卖一张票,剩余:1张 卖一张票,剩余:3张 卖一张票,剩余:2张 卖一张票,剩余:1张
使用Runnable接口实现数据共享的多线程。(核心在于这样的子类可以使用多次start())
1 package Sep18; 2 3 public class ThreadDemo04 { 4 public static void main(String args[]){ 5 MyThread03 mt01=new MyThread03(); 6 new Thread(mt01).start(); 7 new Thread(mt01).start(); 8 new Thread(mt01).start(); 9 10 } 11 } 12 class MyThread03 implements Runnable{ 13 private int ticket=10; 14 public void run(){ 15 for (int i=0;i<=12;i++){ 16 if (ticket>0){ 17 System.out.println("卖一张票,剩余:"+ticket--); 18 } 19 } 20 } 21 }