java语言中,实现线程有两种方式
第一种方式:
编写一个类,直接 继承 java.lang.Thread
,重写 run方法
。
- 怎么创建线程对象? new继承线程的类。
- 怎么启动线程呢? 调用线程对象的
start()
方法。
第二种方式:
编写一个类,实现 java.lang.Runnable
接口,实现run方法
。
- 怎么创建线程对象? new线程类传入可运行的类/接口。
- 怎么启动线程呢? 调用线程对象的
start()
方法。
第三种方式:
Callable创建有返回值的任务
Callable和Future的关系
Callable
和Future
之间的关系是,Callable
表示一个可以在独立线程中执行的任务,而Future
表示这个任务的结果。当通过ExecutorService
提交一个Callable
任务时,会返回一个Future
对象,通过这个Future
对象可以获取任务的执行结果、取消任务等操作。
public class CallableExample {
public static void main(String[] args) {
// 创建一个ExecutorService来执行任务
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 创建一个Callable任务
Callable<Integer> callableTask = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
// 模拟计算任务,这里简单返回一个结果
Thread.sleep(2000);
return 42;
}
};
// 提交Callable任务并获取Future对象
Future<Integer> future = executorService.submit(callableTask);
// 执行其他操作
try {
// 阻塞直到获取任务的结果
Integer result = future.get();
System.out.println("任务结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 关闭ExecutorService
executorService.shutdown();
}
}
ThreadLocal
ThreadLocal
类主要解决的就是让每个线程绑定自己的值
用法:在按上面方法实现的线程类里,加入类似下面的成员,这个成员使用set和get方法操作,在每个线程都是独立的
private static final ThreadLocal<SimpleDateFormat> formatter =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd HHmm"));
最终的变量是放在了当前线程的 ThreadLocalMap
中,并不是存在 ThreadLocal
上,ThreadLocal
可以理解为只是ThreadLocalMap
的封装,传递了变量值。 ThrealLocal
类中可以通过Thread.currentThread()
获取到当前线程对象后,直接通过getMap(Thread t)
可以访问到该线程的ThreadLocalMap
对象。
每个Thread
中都具备一个ThreadLocalMap
,而ThreadLocalMap
可以存储以ThreadLocal
为 key ,Object 对象为 value 的键值对。