创建线程三种方法

简介: 创建线程三种方法

创建和运行线程

方法一,直接使用 Thread

1. // 创建线程对象
2. Thread t = new Thread() {
3. public void run() {
4. // 要执行的任务
5.    }
6. };
7. // 启动线程
8. t.start();

例如:

1. // 构造方法的参数是给线程指定名字,推荐
2. Thread t1 = new Thread("t1") {
3. @Override
4. // run 方法内实现了要执行的任务
5. public void run() {
6.                 log.debug("hello");
7.             }
8.         };
9.         t1.start();

方法二,使用 Runnable 配合 Thread

把【线程】和【任务】(要执行的代码)分开

  • Thread 代表线程
  • Runnable 可运行的任务(线程要执行的代码)
1. Runnable runnable = new Runnable() {
2. public void run() {
3. // 要执行的任务
4.             }
5.         };
6. // 创建线程对象
7. Thread t = new Thread(runnable);
8. // 启动线程
9.         t.start();

例如:

1. public class Test2 {
2.  public static void main(String[] args) {
3.    //创建线程任务
4.    Runnable r = () -> {
5. //直接写方法体即可
6.      System.out.println("Runnable running");
7.      System.out.println("Hello Thread");
8.    };
9.    //将Runnable对象传给Thread
10.     Thread t = new Thread(r);
11.     //启动线程
12.     t.start();
13.   }
14. }

方法三:使用FutureTask与Thread结合

使用FutureTask可以用泛型指定线程的返回值类型(Runnable的run方法没有返回值)

FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况

1. // 创建任务对象
2.         FutureTask<Integer> task3 = new FutureTask<>(() -> {
3.             log.debug("hello");
4. return 100;
5.         });
6. // 参数1 是任务对象; 参数2 是线程名字,推荐
7. new Thread(task3, "t3").start();
8. // 主线程阻塞,同步等待 task 执行完毕的结果
9. Integer result = task3.get();
10.         log.debug("结果是:{}", result);
1. public class Test3 {
2.  public static void main(String[] args) throws ExecutionException, InterruptedException {
3. //需要传入一个Callable对象
4.    FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
5.      @Override
6.      public Integer call() throws Exception {
7.        System.out.println("线程执行!");
8.        Thread.sleep(1000);
9.        return 100;
10.       }
11.     });
12. 
13.     Thread r1 = new Thread(task, "t2");
14.     r1.start();
15.     //获取线程中方法执行后的返回结果
16.     System.out.println(task.get());
17.   }
18. }

方式四:使用线程池例如用Executor框架

参数介绍

1. public ThreadPoolExecutor(int corePoolSize,
2.                               int maximumPoolSize,
3.                               long keepAliveTime,
4.                               TimeUnit unit,
5.                               BlockingQueue<Runnable> workQueue,
6.                               ThreadFactory threadFactory,
7.                               RejectedExecutionHandler handler) {
8. if (corePoolSize < 0 ||
9.             maximumPoolSize <= 0 ||
10.             maximumPoolSize < corePoolSize ||
11.             keepAliveTime < 0)
12. throw new IllegalArgumentException();
13. if (workQueue == null || threadFactory == null || handler == null)
14. throw new NullPointerException();
15. this.acc = System.getSecurityManager() == null ?
16. null :
17.                 AccessController.getContext();
18. this.corePoolSize = corePoolSize;
19. this.maximumPoolSize = maximumPoolSize;
20. this.workQueue = workQueue;
21. this.keepAliveTime = unit.toNanos(keepAliveTime);
22. this.threadFactory = threadFactory;
23. this.handler = handler;
24.     }

* @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set

池中一直保持的线程的数量,即使线程空闲也不会释放。除非设置了 allowCoreThreadTimeOut *

@param maximumPoolSize the maximum number of threads to allow in the * pool

池中允许的最大的线程数

* @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating.

当线程数大于核心线程数的时候,线程在最大多长时间没有接到新任务就会终止释放, 最终线程池维持在 corePoolSize 大小

* @param unit the time unit for the {@code keepAliveTime} argument

时间单位

* @param workQueue the queue to use for holding tasks before they are* executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method.

阻塞队列,用来存储等待执行的任务,如果当前对线程的需求超过了 corePoolSize

大小,就会放在这里等待空闲线程执行。

* @param threadFactory the factory to use when the executor * creates a new thread

创建线程的工厂,比如指定线程名等

* @param handler the handler to use when execution is blocked * because the thread bounds and queue capacities are reached

拒绝策略,如果线程满了,线程池就会使用拒绝策略

运行原理:

1、线程池创建,准备好 core 数量的核心线程,准备接受任务

2、新的任务进来,用 core 准备好的空闲线程执行。

(1) 、core 满了,就将再进来的任务放入阻塞队列中。空闲的 core 就会自己去阻塞队 列获取任务执行

(2) 、阻塞队列满了,就直接开新线程执行,最大只能开到 max 指定的数量

(3) 、max 都执行好了。Max-core 数量空闲的线程会在 keepAliveTime 指定的时间后自 动销毁。最终保持到 core 大小

(4) 、如果线程数开到了 max 的数量,还有新任务进来,就会使用 reject 指定的拒绝策 略进行处理

3、所有的线程创建都是由指定的 factory 创建的。


相关文章
|
3月前
|
Java 调度
Java并发基础-线程简介(状态、常用方法)
Java并发基础-线程简介(状态、常用方法)
32 0
|
17天前
|
存储 Java 程序员
优化Java多线程应用:是创建Thread对象直接调用start()方法?还是用个变量调用?
这篇文章探讨了Java中两种创建和启动线程的方法,并分析了它们的区别。作者建议直接调用 `Thread` 对象的 `start()` 方法,而非保持强引用,以避免内存泄漏、简化线程生命周期管理,并减少不必要的线程控制。文章详细解释了这种方法在使用 `ThreadLocal` 时的优势,并提供了代码示例。作者洛小豆,文章来源于稀土掘金。
|
24天前
|
算法 安全 Java
三种方法教你实现多线程交替打印ABC,干货满满!
本文介绍了多线程编程中的经典问题——多线程交替打印ABC。通过三种方法实现:使用`wait()`和`notify()`、`ReentrantLock`与`Condition`、以及`Semaphore`。每种方法详细讲解了实现步骤和代码示例,帮助读者理解和掌握线程间的同步与互斥,有效解决并发问题。适合不同层次的开发者学习参考。
42 11
|
18天前
|
Java Spring
运行@Async注解的方法的线程池
自定义@Async注解线程池
42 3
|
29天前
|
安全 Java API
|
1月前
|
Java
java开启线程的四种方法
这篇文章介绍了Java中开启线程的四种方法,包括继承Thread类、实现Runnable接口、实现Callable接口和创建线程池,每种方法都提供了代码实现和测试结果。
java开启线程的四种方法
【多线程面试题 二】、 说说Thread类的常用方法
Thread类的常用方法包括构造方法(如Thread()、Thread(Runnable target)等)、静态方法(如currentThread()、sleep(long millis)、yield()等)和实例方法(如getId()、getName()、interrupt()、join()等),用于线程的创建、控制和管理。
|
1月前
|
Dart API C语言
Dart ffi 使用问题之想在C/C++中创建异步线程来调用Dart方法,如何操作
Dart ffi 使用问题之想在C/C++中创建异步线程来调用Dart方法,如何操作
|
1月前
|
Java UED
基于SpringBoot自定义线程池实现多线程执行方法,以及多线程之间的协调和同步
这篇文章介绍了在SpringBoot项目中如何自定义线程池来实现多线程执行方法,并探讨了多线程之间的协调和同步问题,提供了相关的示例代码。
180 0
|
3月前
|
Java 开发者
线程通信的方法和实现技巧详解
线程通信的方法和实现技巧详解