JAVA 线程实现/创建方式

java

每天记录一个知识点;


概要:

java创建线程的方式:

  1. 继承Thread类
  2. 实现Runnable接口
  3. 通过Callable和Future创建线程
  4. 基于线程池的方式

java创建线程池的四种方式:

  1. newCachedThreadPool 创建一个可缓存的线程池,如果线程池长度超过处理需求,可灵活回收空闲线程,若无可回收,则新建线程
  2. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
  3. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行
  4. newSingleThreadExecutor 创建一个单线程化的线程池,它只会唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行

线程创建

继承 Thread 类

Thread 类本质上是实现了 Runnable 接口的一个实例,代表一个线程的实例。
⭐继承Thread类的话,必须重写run方法 ,在run方法中定义需要执行的任务。
⭐启动线程的 唯一方法 就是通过 Thread 类的 start() 实例方法。start()方法是一个 native 方法,它将启动一个新线程,并执行 run()方法。

注意,不是调用run()方法启动线程,run方法中只是定义需要执行的任务,如果调用run方法,即相当于在主线程中执行run方法,跟普通的方法调用没有任何区别,此时并不会创建一个新的线程来执行定义的任务。

public class MyThread extends Thread {
	public void run() {
		System.out.println("MyThread.run()");
	}
}
MyThread myThread1 = new MyThread();
myThread1.start();

实现 Runnable 接口

除了继承Thread类之外,还可以通过实现Runnable接口来创建线程(例如:如果自己的类已经 extends 另一个类,就无法直接 extends Thread,此时可以实现一个Runnable 接口)。实现Runnable接口必须重写其run方法。

class MyRunnable implements Runnable{
    public MyRunnable() {
    }
    @Override
    public void run() {
        System.out.println("子线程ID:"+Thread.currentThread().getId());
    }
}

public class Main {
  public static void main(String[] args){
    //创建并启动线程
    MyThread2 myThread=new MyThread2();
    Thread thread=new Thread(myThread);
    thread().start();
    //或者    new Thread(new MyThread2()).start();
  }
}

ExecutorService、 Callable、 Future 有返回值线程

有返回值的任务必须实现 Callable 接口,类似的,无返回值的任务必须 Runnable 接口。执行Callable 任务后,可以获取一个 Future 的对象,在该对象上调用 get 就可以获取到 Callable 任务返回的 Object 了,再结合线程池接口 ExecutorService 就可以实现传说中有返回结果的多线程了。

//创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
// 创建多个有返回值的任务
List<Future> list = new ArrayList<Future>();
for (int i = 0; i < taskSize; i++) {
	Callable c = new MyCallable(i + " ");
	// 执行任务并获取 Future 对象
	Future f = pool.submit(c);
	list.add(f);
}
// 关闭线程池
pool.shutdown();
// 获取所有并发任务的运行结果
for (Future f : list) {
	// 从 Future 对象上获取任务的返回值,并输出到控制台
	System.out.println("res: " + f.get().toString());
}

基于线程池的方式

线程和数据库连接这些资源都是非常宝贵的资源。那么每次需要的时候创建,不需要的时候销毁,是非常浪费资源的。那么我们就可以使用缓存的策略,也就是使用线程池。

// 创建线程池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
threadPool.execute(new Runnable() { // 提交创建线程任务,并执行
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + " is running ..");
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
		e.printStackTrace();
		}
	}
});

posted @ 2021-03-17 18:57  super_龙  阅读(90)  评论(0编辑  收藏  举报