线程的创建

多线程:

线程有四种创建方式:

继承Thread,重写run方法
实现Runnable接口
实现Callable接口
线程池

注意: 启动线程就是指请求jvm运行相应的程序
启动线程不代表线程就会立即运行,由线程调度器(scheduler)决定

第一种:

1)继承Thread,并且重写run方法:
重写父类的run()方法

package com.itjh.pojo;

public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 200; i++) {
        //被调用时获得当前线程的名字,主方法中的`.start()`就表示被调用
            System.out.println(getName()+"。。。子线程。。。。。"+i);
        }
    }
}

2)创建一个主线程:

实例化MyThread类,调用start()方法,意为自动开启线程,并且他会自动去调用MyThread()类中的run()方法
主线程和MyThread子线程的执行顺序与代码放置的顺序是无关的,但是一个方法同一个类中的方法是按照顺序来的,主线程第 执行完毕后才会执行.......主方法.......

package com.itjh.Test;

import com.itjh.pojo.MyThread;

public class Test01 {
    public static void main(String[] args) {
        MyThread myThread=new MyThread();
        //给子线程起个名字!!!
        myThread.setName("子线1==");
        myThread.start();
        for (int i = 0; i < 200; i++) {
            System.out.println("主线程"+i);
        }
        System.out.println(".......主方法.......");
    }
}

结果大概这样:

主线程196
主线程197
主线程198
主线程199
子线1==。。。子线程。。。。。132
子线1==。。。子线程。。。。。133
子线1==。。。子线程。。。。。134
子线1==。。。子线程。。。。。135
.......主方法.......
子线1==。。。子线程。。。。。136
子线1==。。。子线程。。。。。137

第二种方法:

1)创建MyRunnable类实现Runnable类,并且重写run()方法

package com.one;

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 300; i++) {
            System.out.println("子线程实现Runnable第"+i);
        }
    }
}

2)创建主线程:

先实例化Thread,将MyRunnable传进去,在Thread类中有很多构造方法:
如:
线程的创建_第1张图片
这里我采用第三个构造函数,传进去一个实现类和自定义线程名

import com.one.MyRunnable;

public class MyRunnableTest {
    public static void main(String[] args) {
        Thread thread=new Thread(new MyRunnable());
        thread.start();
        for(int i=0;i<300;i++){
            System.out.println("主线程第"+i);
        }
    }
}

结果是乱序的,也可能是顺序的

第三种:

线程的创建_第2张图片

思路:Callable接口要借助于FutureTask类来创建线程,FutureTask继承了Runnable接口,所以,将他放入Thread实例化进行的构造函数传参中,Thread . start()开启线程

创建新的类实现Callable接口,并且重写其中的call()方法:

package com.itjh.pojo;

import java.util.concurrent.Callable;

public class MyCallable implements Callable {
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            sum=sum+i;
        }
        return sum;
    }
}

创建主线程:

package com.itjh.Test;

import com.itjh.pojo.MyCallable;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Test03 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //先获得的一个自己创建的MyCallable对象,即子线程
        MyCallable myCallable=new MyCallable();
        //创建FutureTask接收子线程进行管理,并设置管理的子线程的返回值为Integer
        FutureTask<Integer> futureTask=new FutureTask(myCallable);
        //FutureTask最终继承了Runnable类,所以直接扔进Tread中
        Thread thread=new Thread(futureTask);
        thread.start();
        //用FutureTask的get()方法获得返回值,并打印
        Integer i =futureTask.get();
        System.out.println(i);
    }
}

为什么不直接将Callable实现类放在Thread实例化中呢?为什么要用要借助FutureTask才能创建基于Callable接口的实现类的线程呢?

1、因为Tread构造方法中没有Callable的返回类型
2、FutureTask实现了RunnableFuture接口,而RunnableFuture接口又继承了Runnable接口,在Thread类中有参数类型为Runnable的构造方法,FutureTask类中有参数类型为Callable的构造函数,综上所述,所以要借助FutureTask创建线程

第四种:

线程池

创建线程的各种方法对比:

线程的创建_第3张图片
图片摘自:https://www.bilibili.com/video/BV1ut411T7Yg?p=8

你可能感兴趣的:(java,开发语言,后端)