欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java中多线程 - 如何创建多线程

程序员文章站 2022-06-06 18:56:42
线程 什么是线程: 线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源 表面上是多线程其实是cpu快速轮流切执行 多线程(并行和并发) 1. 并行:两个任务同事进行,就是甲任务执 ......

线程

什么是线程:

 线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源

表面上是多线程其实是cpu快速轮流切执行

多线程(并行和并发)

  1. 并行:两个任务同事进行,就是甲任务执行的同时,乙任务也在执行(需要多核)
  2. 并发:两个任务都请求运行,而处理器只能接受一个任务,就把这两个任务安排轮流执行。由于时间间隔很短,使人感觉两个任务都在运行

多线程(java程序运行的原理)

java命令会启动jvm等于启动了一个应用程序(一个进程)。该进程会自动启动“主线程”,主线程去调用main方法

启动jvm是单线程的么?

不是,是多线程的。至少会启动垃圾回收线程和主线程

可通过下面代码来验证,主线程和垃圾回收线程在互相抢占资源

public class testthread {

    public static void main(string[] args) {
        //4.创建thread的子类对象
        mythread mythread = new mythread();

        //5.启动线程,注意这里使用的是start而不是run方法
        mythread.start();

        for (int i = 0; i < 10000; i ++) {
            system.out.println("this is main thread");
        }
    }


}

//1.继承thread
class mythread extends  thread{

    //2.重写run方法
    @override
    public void run() {
        super.run();
        //3.线程方法中要执行的代码,可以根据自己的需求填写
        for(int i = 0 ; i < 10000 ; i ++ ) {
            system.out.println("this is mythread thread ");
        }
    }
}

java中如何创建多线程

(1)继承thread类并调用start方法

thread实现了runnable接口
要实现多线程,就要成为thread的子类,并且重写run方法。注意在启动线程的时候,调用的不是run方法而是start方法。如果调用run方法,那么相当于一个普通方法并不会开启线程

public class thread implements runnable 
public class testthread {

    public static void main(string[] args) {
        mythread mythread = new mythread();
        //注意这里使用的是start而不是run方法
        mythread.start();

        for (int i = 0; i < 10000; i ++) {
            system.out.println("this is main thread");
        }
    }


}

class mythread extends  thread{

    @override
    public void run() {
        super.run();

        for(int i = 0 ; i < 10000 ; i ++ ) {
            system.out.println("this is mythread thread ");
        }
    }
}

(2)实现runnable接口,并重写run方法

runnable中只有一个方法run(),而线程启动方法存在与thread中,
那么我们在最终启动线程的时候,势必是要通过thread的子类对象去启动线程的
public class testrunnable {

    public static void main(string[] args) {
        //4.创建thread的子类对象
        runnable myrunnable = new myrunnable();

        //5.启动线程,创建thread并把runnable的子类作为构造参数
        new thread(myrunnable).start();

        for (int i = 0; i < 10000; i ++) {
            system.out.println("this is main thread");
        }
    }


}
//1.实现runnable接口
class myrunnable implements runnable {

    //2.重写run方法
    @override
    public void run() {
        //3.线程方法中要执行的代码,可以根据自己的需求填写
        for(int i = 0 ; i < 10000 ; i ++ ) {
            system.out.println("this is myrunnable thread ");
        }
    }
}

实现callable接口

要实现线程,除了继承thread和runnable,还可以实现callable接口。callable接口提供了一个call()方法可以作为线程执行体,和run()的作用一样。但call()方法比run()方法多了返回值,call()方法可以声明抛出的异常。那么我们如何开启callable线程呢?因为callable接口不是runnable接口的子接口,所以callable对象不能作为thread的构造参数。java提供了另一个接口runnablefuture接口,该接口实现了runnable, future

  1. 实现callable接口
  2. 重写call方法,相当于thread中的run方法。不同的是call方法允许有返回值
  3. 把callable实现类对象作为构造参数传入futuretask创建futuretask对象。
  4. 把futuretask对象作为构造参数传入thread,并开启线程
public class callabledemo {

    public static void main(string[] args) {
        //3.把callable实现类对象作为构造参数传入futuretask创建futuretask对象。
        futuretask<uuid> futuretask = new futuretask<uuid>(new mycallable());
        //4.把futuretask对象作为构造参数传入thread,并开启线程
        new thread(futuretask).start();
        try {
            system.out.println(futuretask.get());
        } catch (interruptedexception e) {
            e.printstacktrace();
        } catch (executionexception e) {
            e.printstacktrace();
        }
    }
}

//1. 实现**callable**接口
class mycallable implements callable<uuid> {

    //2.重写**call**方法,相当于thread中的run方法。不同的是call方法允许有返回值
    @override
    public uuid call() throws exception {
        //生成随机数
        return uuid.randomuuid();
    }
}

继承thread,实现runnable和callable的区别

从源码的实现上

继承thread

子类重写thread中的run()方法,调用start()方法,jvm会自动调用子类的run()

实现runnable

new thread(myrunnable)在thread的构造函数中参入runnable的引用,然后传给thread的成员变量target。在thread run()方法中判断了如果target不为空,就调用子类的run方法

    public void run() {
    if (this.target != null) {
        this.target.run();
    }

实现callable接口

实现callable接口重写call()方法,并且可以提供线程返回值,也可以抛出异常。最终通过runnable的子接口runnablefuture的实现类futuretask,传给thread的成员变量target。

从使用上和拓展上

继承thread

  1. 优点:直接调用thread中的start()方法,十分简单
  2. 缺点:java只支持单继承,如果子类继承了thread无法再继承其他类

实现runnable

  1. 优点:java可以多实现
  2. 缺点:代码书写比较复杂,不能直接调用start()

实现callable

  1. 优点:java可以多实现,可以抛出异常,可以有返回值
  2. 缺点:代码书写比较复杂