多线程结合案例详解


                                                                   多线程结合案例详解



java的多线程实现


在java中,如果要想实现多线程,可以采用以下两种方式:
1、继承Thread类
2、实现Runnable接口

继承Thread类

Thread类是在java.lang包中的定义,一个类只要继承了Thread类,此类就称为多线程操作类。在Thread子类中,必须明确覆写Thread类中的run()方法,此方法为线程的主体。

以下结合一个 例子看看:
package com.ywx;

class MyThread extends Thread{
	private String name;
	public MyThread(String name){
		this.name=name;
	}
	public void run(){
		for(int i=0;i<10;i++){
			System.out.println(name+"运行i="+i);
		}
	}
}
public class ThreadDemo1 {
	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

分析:以上程序是先执行完A之后再执行B,并没有达到所谓的并发执行的效果。
因为以上的程序实际上还是按照古老的形式调用的,通过对象.方法,但是如果想要启动一个线程必须使用Thread类中定义的start()方法。
一旦调用start()方法,实际上最终调用的就是run()方法。

再看一下程序:

package com.ywx;

class MyThread extends Thread{
	private String name;
	public MyThread(String name){
		this.name=name;
	}
	public void run(){
		for(int i=0;i<10;i++){
			System.out.println(name+"运行i="+i);
		}
	}
}
public class ThreadDemo1 {
	public static void main(String[] args) {
		MyThread mt1 = new MyThread("线程A"); 
		MyThread mt2 = new MyThread("线程B"); 
		mt1.start();
		mt2.start();
	}
}
运行结果:

线程A运行i=0
线程A运行i=1
线程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
线程A运行i=2
线程A运行i=3
线程A运行i=4
线程A运行i=5
线程A运行i=6
线程A运行i=7
线程A运行i=8
线程A运行i=9

分析:从此处的效果来看,确实是并发执行的,那个线程先抢占到了cup资源,那个线程就执行。


实现Runnable接口

在java中也可以通过实现Runnable接口的方式实现多线程,看以下例子:

package com.ywx;

class MyThread implements Runnable{
	private String name;
	public MyThread(String name){
		this.name=name;
	}
	public void run(){
		for(int i=0;i<10;i++){
			System.out.println(name+"运行i="+i);
		}
	}
}
public class RunnableDemo {
	public static void main(String[] args) {
		MyThread mt1 = new MyThread("线程A"); 
		MyThread mt2 = new MyThread("线程B"); 
		Thread thread1 = new Thread(mt1);
		Thread thread2 = new Thread(mt2);
		thread1.start();
		thread2.start();
	}
}

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

结果分析:以上运行可以达到并发执行。

Thread类于Runnable接口的联系


Thread类是Runnable接口的子类。

关系图如下:



                                                      多线程结合案例详解_第1张图片

从类的关系图来看,之前的做法非常类似于代理设计模式,Thread类完成比线程主体更多的操作。
例如:分配CPU资源,判断是否已经启动等等。

Thread类与Runnable接口的区别

使用Thread类在操作多线程的时候无法达到资源共享的目的,而使用Runnable接口实现多线操作则可以达到资源共享。以下通过一个例子分析:
package com.ywx;

class MyThread extends Thread{
	private int ticket=5;
	private String name;
	public MyThread(String name){
		this.name=name;
	}
	public void run(){
		for(int i=0;i<100;i++){
			if(this.ticket>0){
				System.out.println(name+"卖票,实票ticket="+ticket--);
			}
		}
	}
}
public class ThreadDemo {
	public static void main(String[] args) {
		MyThread mt1 = new MyThread("线程A"); 
		MyThread mt2 = new MyThread("线程B"); 
		
		mt1.run();
		mt2.run();
	}
}

运行结果:
线程A卖票,实票ticket=5
线程A卖票,实票ticket=4
线程A卖票,实票ticket=3
线程A卖票,实票ticket=2
线程B卖票,实票ticket=5
线程A卖票,实票ticket=1
线程B卖票,实票ticket=4
线程B卖票,实票ticket=3
线程B卖票,实票ticket=2
线程B卖票,实票ticket=1

分析:通过运行效果可以看出,一个卖出了10张票,也就是线程之间是可执行各自的,没有达到资源共享的目的。
没有达到资源共享的原因:因为在每一个Thread对象中都包含各自的ticket属性。

要想达到资源共享,则需要实现Runnable接口,看以下例子:


package com.ywx;

class MyThread implements Runnable{
	private int ticket=5;
	public void run(){
		for(int i=0;i<100;i++){
			if(this.ticket>0){
				System.out.println("卖票,实票ticket="+ticket--);
			}
		}
	}
}
public class RunnableDemo {
	public static void main(String[] args) {
		MyThread mt1 = new MyThread(); 
		Thread thread1 = new Thread(mt1);
		Thread thread2 = new Thread(mt1);
		thread1.start();
		thread2.start();
	}
}

运行结果:
卖票,实票ticket=5
卖票,实票ticket=4
卖票,实票ticket=3
卖票,实票ticket=2
卖票,实票ticket=1

结果分析:

从运行的结果来看,虽然我们启动了两个线程,但是两个线程工卖出5张票,所有达到了资源共享的目的。

结论:Thread类和Runnable接口的使用结论

实现Runnable接口比继承Thread类有如下的明显有点:
1、适合多个相同程序代码的线程去处理同一个资源。
2、可以避免由于但继承局限所带来的影响。
3、增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。







你可能感兴趣的:(多线程结合案例详解)