java线程
创建线程俩个有俩种
1实现 Runnable 接口
2 继承 Thread 类
最好的方法使用接口,因为可以实现多个类,还能继承
就绪状态、运行状态、阻塞状态 线程活着
isAlive()判断线程是否”活着“
getPriority() 获得线程优先级
setPriority() 设置线程优先级,最小1最大10 默认5
(最小Thread.MIN_PRIORITY最大Thread.MAX_PRIORITY,默认Thread.NORM_PRIORITY )
Thread.sleep() 指定当前线程睡眠毫秒数
join() 调用某线程该方法,将当前线程与该线程合并,等待该线程结束,再恢复当前线程
yield() 让出cpu,当前线程进入就绪队列,等待调度
wait() 当前线程进入对象的wait pool
notify()/notifyAll() 唤醒对象wait pool 中一个/所有 等待线程
currentThread():静态⽅法,返回对当前正在执⾏的线程对象的引⽤;
实现Runable 或继承 Thread 类 会实现一个run方法,run方法是共用的,new出多少个线程都会去实现这个run方法
synchronized(this) 锁定当前对象,互斥锁(执行这个方法的过程中,当前对象被锁定,保证只有一个线程进入这个方法体中),使线程同步(如:执行共享数据,需要添加锁)
synchronized 锁定方法的当前对象,另外线程可以访问没有锁定方法
除了Thread和Runable,还有其他的接口和类
Callable:Callable 与 Runable 类 ,Callable 提供的⽅法是有返回值的,⽽且⽀持泛型。
@FunctionalInterface public interface Callable<V> { V call() throws Exception; }
Callable ⼀般是配合线程池⼯具 ExecutorService 来使⽤的, ExecutorService 可以使⽤ submit ⽅法来让⼀个 Callable 接⼝执⾏。它会返回
⼀个 Future ,后续的程序可以通过这个 Future 的 get ⽅法得到结果。
// ⾃定义Callable class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { // 模拟计算需要⼀秒 Thread.sleep(1000); return 2; } public static void main(String args[]){ // 使⽤ ExecutorService executor = Executors.newCachedThreadPool(); Task task = new Task(); Future<Integer> result = executor.submit(task); // 注意调⽤get⽅法会阻塞当前线程,直到得到结果。 // 所以实际编码中建议使⽤可以设置超时时间的重载get⽅法。 System.out.println(result.get()); } }
输出结果 2
Future接⼝
public abstract interface Future<V> { public abstract boolean cancel(boolean paramBoolean); public abstract boolean isCancelled(); public abstract boolean isDone(); public abstract V get() throws InterruptedException, ExecutionException; public abstract V get(long paramLong, TimeUnit paramTimeUnit) throws InterruptedException, ExecutionException, TimeoutException; }
cancel ⽅法是试图取消⼀个线程的执⾏。注意是试图取消,并不⼀定能取消成功。因为任务可能已完成、已取消、或者⼀些其它因素不能取消,存在取消失败的可能。
boolean 类型的返回值是“是否取消成功”的意思。参数 paramBoolean 表示是否采⽤中断的⽅式取消线程执⾏。
所以有时候,为了让任务有能够取消的功能,就使⽤ Callable 来代替 Runnable 。
如果为了可取消性⽽使⽤ Future 但⼜不提供可⽤的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。
FutureTask类
Future 接⼝。这个接⼝有⼀个实现类叫 FutureTask 。 FutureTask 是实现的 RunnableFuture 接⼝的,⽽ RunnableFuture 接⼝同时继承了 Runnable 接⼝和 Future 接⼝
public interface RunnableFuture<V> extends Runnable, Future<V> { /** * Sets this Future to the result of its computation * unless it has been cancelled. */ void run(); }
为什么要有⼀个 FutureTask 类?Future 只是⼀个接⼝,⽽它⾥⾯的 cancel , get , isDone 等⽅法要⾃⼰实现
起来都是⾮常复杂的。所以JDK提供了⼀个 FutureTask 类来供我们使⽤。
// ⾃定义Callable,与上⾯⼀样 class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { // 模拟计算需要⼀秒 Thread.sleep(1000); return 2; } public static void main(String args[]){ // 使⽤ ExecutorService executor = Executors.newCachedThreadPool(); FutureTask<Integer> futureTask = new FutureTask<>(new Task()); executor.submit(futureTask); System.out.println(futureTask.get()); } }
⾸先,调⽤ submit ⽅法是没有返回值的。这⾥实际上是调⽤的 submit(Runnable task) ⽅法,⽽上⾯的Demo,调⽤的是 submit(Callable<T> task) ⽅法。
然后,这⾥是使⽤ FutureTask 直接取 get 取值,⽽上⾯的Demo是通过 submit ⽅法返回的 Future 去取值。
在很多⾼并发的环境下,有可能Callable和FutureTask会创建多次。FutureTask能够在⾼并发环境下确保任务只执⾏⼀次。