Java多线程(一)Thread类与Runnable接口

来源:互联网 发布:如何评价彭德怀 知乎 编辑:程序博客网 时间:2024/06/06 01:38

1、线程

a 进程、线程都是实现并发机制的有效手段;

b 线程是比进程更小的执行单位,是在进程基础上的进一步划分;

c 一个程序运行,可能多个线程同时运行

例如,打开word是启动了一个系统进程,里面的拼写检查就是一个小的线程。

2、Thread类

Thread类属于java.lang.Object。在文档中的定义:public class Thread extends Object implements Runnable

可以看出,Thread类也实现了Runnable接口,一个类要继承thread类必须重写run()方法。

实例:

定义一个线程类MyThread实现Thread

public class MyThread extends Thread{private String name;//再类中定义一个属性public MyThread(String name){this.name = name;}//一定要重写Thread类中的run()方法,此方法为线程的主体public void run(){for(int i=0; i<10; i++){System.out.println(name+"运行, i="+i);}}}
实例化并运行下run()方法:

public class ThreadDemo01 {public static void main(String[] args) {MyThread mt1 = new MyThread("线程A");MyThread mt2 = new MyThread("线程B");mt1.run();mt2.run();}}

运行结果:

线程A运行, i=0线程A运行, i=1线程A运行, i=2线程A运行, i=3线程A运行, i=4线程A运行, i=5线程A运行, i=6线程A运行, i=7线程A运行, i=8线程A运行, i=9线程B运行, i=0线程B运行, i=1线程B运行, i=2线程B运行, i=3线程B运行, i=4线程B运行, i=5线程B运行, i=6线程B运行, i=7线程B运行, i=8线程B运行, i=9

可以看出先执行了mt1后执行mt2,并没有交错同时运行,所以以上方法并没有启动多线程。

要想使用多线程,必须调用从Thread类中继承来的start()方法。

public class ThreadDemo02 {public static void main(String[] args) {MyThread mt1 = new MyThread("线程A");MyThread mt2 = new MyThread("线程B");mt1.start();mt2.start();}}
运行结果:(可能的一种)

线程B运行, i=0线程A运行, i=0线程B运行, i=1线程A运行, i=1线程B运行, i=2线程A运行, i=2线程B运行, i=3线程A运行, i=3线程B运行, i=4线程A运行, i=4线程B运行, i=5线程B运行, i=6线程A运行, i=5线程B运行, i=7线程A运行, i=6线程A运行, i=7线程A运行, i=8线程A运行, i=9线程B运行, i=8线程B运行, i=9

以上实现了多线程,两个线程交错运行,哪个线程对象抢到了CPU资源,哪个线程就可以运行。

注:如果一个类通过继承Thread类来实现,那么只能调用一次start()方法,若调用多次就会抛出异常

mt1.start();

mt2.start();

异常:java.lang.IllegalThreadStateException

3、Runnable接口

下面通过实例看实现Runnable接口如何启动多线程

还是那个线程类我们让他实现Runnable接口

public class MyThread2 implements Runnable{private String name;public MyThread2(String name){this.name = name;}//重写Runnable接口中的run()方法public void run(){for(int i=0; i<10; i++){System.out.println(name+"运行, i="+i);}}}
实例化启动线程:

public class ThreadDemo04 {public static void main(String[] args) {MyThread2 mt1 = new MyThread2("线程A");MyThread2 mt2 = new MyThread2("线程B");Thread t1 = new Thread(mt1);Thread t2 = new Thread(mt2);t1.start();t2.start();}}

运行结果:

线程A运行, i=0线程B运行, i=0线程A运行, i=1线程B运行, i=1线程A运行, i=2线程B运行, i=2线程A运行, i=3线程A运行, i=4线程A运行, i=5线程A运行, i=6线程A运行, i=7线程A运行, i=8线程A运行, i=9线程B运行, i=3线程B运行, i=4线程B运行, i=5线程B运行, i=6线程B运行, i=7线程B运行, i=8线程B运行, i=9
要想启动一个多线程,必须调用start()方法,如果继承thread类就可以直接使用其start()方法;Runnable接口没有start()方法的定义,还是要依靠thread类。

实例化Runnable子类对象--->用Runnable实例去实例化Thread类对象----->启动线程通过thread实例对象

4、Thread类与Runnable接口

Thread类:通过子类继承,有单继承局限;不能一个实例重复调用start()方法,不能实现资源共享。

Runnable:避免单继承局限;可被多个线程共享;

下面通过一个卖票的实例来对比资源共享的问题

定义一个线程类继承Thread类:

public class MyThread3 extends Thread{private int ticket = 5;//一共5张票public void run(){for(int i=0; i<100; i++){//超出票数的循环,卖完即止if(ticket > 0){System.out.println("卖票:ticket="+ticket--);}}}}
实例化启动线程:

public class ThreadDemo05 {public static void main(String[] args) {MyThread3 my1 = new MyThread3();MyThread3 my2 = new MyThread3();MyThread3 my3 = new MyThread3();my1.start();my2.start();my3.start();}}

运行结果:

卖票:ticket=5卖票:ticket=5卖票:ticket=5卖票:ticket=4卖票:ticket=3卖票:ticket=4卖票:ticket=2卖票:ticket=1卖票:ticket=3卖票:ticket=4卖票:ticket=2卖票:ticket=1卖票:ticket=3卖票:ticket=2卖票:ticket=1
以上启动了三个线程,但是每个线程却卖了各自的5张票,没有实现资源共享。

实现Runnable接口,来线程资源共享

定义一个线程类实现Runnable接口:

public class MyThread4 implements Runnable{private int ticket = 5;@Overridepublic void run() {for(int i=0; i<100; i++){if(ticket > 0){System.out.println("卖票:ticket="+ticket--);//第一次循环ticket--为5,ticket变为4}}}}
实例化调用Thread的start()启动线程:

public class ThreadDemo06 {public static void main(String[] args) {MyThread4 my = new MyThread4();new Thread(my).start();new Thread(my).start();new Thread(my).start();}}

运行结果:

卖票:ticket=5卖票:ticket=3卖票:ticket=4卖票:ticket=1卖票:ticket=2

启动了三个线程,一共随机卖出这5张票,实现了资源贡献

1 0
原创粉丝点击