(Java)Java 中线程的实现

Java 中要想实现多线程代码有两种手段,一种是继承 Thread 类,另一种就是实现 Runnable 接口

开发工程中,建议使用 Runnable 接口实现多线程

一、继承 Thread 类

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

class 类名称 extends Thread{//继承 Thread 类
	属性;//类中定义属性
	方法;//类中定义方法
	public void run(){//覆写 Thread 类中的 run() 方法,此方法时线程的主体
		线程主体;
	}
}

程序的调用从 Thread 类中继承而来的 start() 方法,而不是 run()方法。

class MyThread extends Thread{//继承 Thread 类
    private String name;
    public MyThread(String name){
        this.name = name;
    }
    public void run(){//覆写 Thread 类中的 run() 方法
        for(int i=0;i<10;i++){//循环 10 次输出
            System.out.println(name + "运行,i = " + i);
        }
    }
}

public class Root{
    public static void main(String[] args) {
        MyThread mt1 = new MyThread("线程 A");//实例化对象
        MyThread mt2 = new MyThread("线程 B");//实例化对象
        mt1.start();//启动多线程
        mt2.start();//启动多线程
    }
}

在这里插入图片描述
由结果(可能结果的一种)可知,两个线程现在是交错运行,哪个线程对象抢到了 CPU资源,哪个线程就可以运行,所以程序每次的运行结果肯定是不一样的,在线程启动时虽然是调用的是 start() 方法,但是实际上调用的却是 run() 方法的主

如果一个类通过继承 Thread 类来实现,那么只能调用一次 start() 方法,如果调用多次,则将会抛出“IllegalThreadStateException” 异常

多线程的实现需要依靠底层操作系统支持

二、实现 Runnable 接口

在 Java 中也可以通过实现 Runnable 接口的方式实现多线程,Runnable 接口中只定义了一个抽象方法:

public void run();

使用 Runnable 接口实现多线程的格式如下:

class 类名称 implements Runnable{//实现 Runnable 接口
	属性...;
	方法...;
	public void run(){//覆写 Runnable 接口中的 run() 方法
		线程主体;
	}
}

示例:

class MyThread implements Runnable{//继承 Runnable 接口
    private String name;
    public MyThread(String name){
        this.name = name;
    }
    public void run(){//覆写 Thread 类中的 run() 方法
        for(int i=0;i<5;i++){//循环 10 次输出
            System.out.println(name + "运行,i = " + i);
        }
    }
}

这里通过 Runnable 接口实现了多线程,如果想要实现 Runnable 接口,还是要依靠 Thread 类完成启动,在 Thread 类中提供了
public Thread(Runnable target)public Thread(Runnable target,String name) 两个构造方法。

这两个构造方法都可以接收 Runnable 的子类实例对象,所以就可以依靠此点启动多线程:

class MyThread implements Runnable{//继承 Runnable 接口
    private String name;
    public MyThread(String name){
        this.name = name;
    }
    public void run(){//覆写  run() 方法
        for(int i=0;i<5;i++){//循环 10 次输出
            System.out.println(name + "运行,i = " + i);
        }
    }
}
public class Root{
    public static void main(String[] args) {
        MyThread my1 = new MyThread("线程 A");//实例化Runnable子类对象
        MyThread my2 = new MyThread("线程 B");//实例化Runnable子类对象
        Thread t1 = new Thread(my1);//实例化 Thread 类对象
        Thread t2 = new Thread(my2);//实例化 Thread 类对象
        t1.start();//启动多线程
        t2.start();//启动多线程
    }
}

在这里插入图片描述

三、Thread 类和 Runnable 接口

如果一个类继承 Thread 类,则不适合于多个线程共享资源,而实现了 Runnable 接口,就可以方便地实现资源的共享

  1. 继承 Thread 类不能资源共享
class MyThread extends Thread{//继承 Thread 类
    private int ticket = 5;//一共 5 张票
    public void run(){//覆写 Thread 类中的 run() 方法
        for(int i=0;i<10;i++){//超出票数的循环
            if(ticket>0){//判断是否有剩余票
                System.out.println("卖票:ticket = " + ticket--);
            }
        }
    }
}

public class Root{
    public static void main(String[] args) {
        MyThread mt1 = new MyThread();//定义线程对象
        MyThread mt2 = new MyThread();//定义线程对象
        MyThread mt3 = new MyThread();//定义线程对象
        mt1.start();//启动第 1 个线程
        mt2.start();//启动第 2 个线程
        mt3.start();//启动第 3 个线程
    }
}

在这里插入图片描述
程序通过 Thread 类实现多线程,程序中启动了 3 个线程,但是 3 个线程却分别卖了各自的 5 张票,并没有达到资源共享的目的。

这里也不能像 Runnable 一样实例化一个,启动两个start,因为如果一个类通过继承 Thread 类来实现,那么只能调用一次 start() 方法,否则就会报错。
错误的代码

public class Root{
    public static void main(String[] args) {
        MyThread mt1 = new MyThread();//定义线程对象
        mt1.start();//启动第 1 个线程
        mt1.start();//启动第 1 个线程
    }
}
  1. 实现 Runnable 接口可以资源共享
class MyThread implements Runnable{//继承 Runnable 接口
    private int ticket = 5;//一共 5 张票
    public void run(){//覆写 Thread 类中的 run() 方法
        for(int i=0;i<10;i++){//超出票数的循环
            if(ticket>0){//判断是否有剩余票
                System.out.println("卖票:ticket = " + ticket--);
            }
        }
    }
}

public class Root{
    public static void main(String[] args) {
        MyThread my = new MyThread();//定义线程对象
        //启动两个线程来完成这个线程对象
        new Thread(my).start();//启动第 1 个线程
        new Thread(my).start();//启动第 2 个线程
    }
}

在这里插入图片描述
这里的意思是实例化一个线程对象,通过两个线程同时去执行它,这个过程中还是通过 Thread 来启动多个线程的。

Runnable 接口相对于继承 Thread 类的优势
(1)适合多个相同程序代码的线程去处理同一资源的情况
(2)可以避免由于 Java 的单继承特性带来的局限
(3)增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的

发布了514 篇原创文章 · 获赞 248 · 访问量 21万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 撸撸猫 设计师: 设计师小姐姐

分享到微信朋友圈

×

扫一扫,手机浏览