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运行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
线程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接口的子类。
关系图如下:
从类的关系图来看,之前的做法非常类似于代理设计模式,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
线程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
卖票,实票ticket=4
卖票,实票ticket=3
卖票,实票ticket=2
卖票,实票ticket=1
结果分析:
从运行的结果来看,虽然我们启动了两个线程,但是两个线程工卖出5张票,所有达到了资源共享的目的。
结论:Thread类和Runnable接口的使用结论
实现Runnable接口比继承Thread类有如下的明显有点:
1、适合多个相同程序代码的线程去处理同一个资源。
2、可以避免由于但继承局限所带来的影响。
3、增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。
版权声明:本文为yangwenxue_admin原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。