创建线程的三种方式
public class MyThread extends Thread { @Override public void run() { } } new MyThread().start(); new Thread(new Runnable() { @Override public void run() { } }).start(); FutureTask<String> task = new FutureTask<String>(new Callable<String>() { @Override public String call() throws Exception { return null; } }); new Thread(task).start(); try { String result = task.get(); // 阻塞式取值 } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); }线程常用方法
thread.isAlive(); // 判断线程是否活动(是否已经start并且尚未结束) thread.join(); // 当前线程会等待thread执行返回 thread.setDaemon(true); // 设置为后台线程(当只有后台线程时,进程会结束) thread.setPriority(Thread.MAX_PRIORITY); // 优先级 Thread.yield(); // 暂停一下
两种线程同步方式
同步监视器同步监视器 synchronized 同步代码块、同步方法 sleep、yield 不会释放同步锁 wait 会释放同步锁(wait需要synchronized括号里的那个东西来调用,它是一个Object方法) wait、notify、notifyAll
同步锁(ReentrantLock、ReentrantReadWriteLock)简单用法:
private final ReentrantLock lock = new ReentrantLock(); public void dosomething() { lock.lock(); // tryLock、lockInterruptibly try { // TODO } finally { lock.unlock(); } }带条件用法:
private final ReentrantLock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); public void dosomething() { lock.lock(); try { if (true) // 根据业务替换其它条件 { condition.await(); } else { condition.signalAll(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } }阻塞队列(BlockingQueue)
阻塞队列(BlockingQueue)可用于一个线程存,一个线程取的情况
常用实现类:
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(2);线程组 ThreadGroup 用于管理线程,它可以是个树组合(因为有getParent方法)
常用方法
threadGroup.activeCount(); threadGroup.interrupt(); threadGroup.isDaemon(); threadGroup.setDaemon(true);
线程池常规用法
ExecutorService pool = Executors.newFixedThreadPool(5); pool.execute(new Runnable() { @Override public void run() { } }); Future<String> result = pool.submit(new Callable<String>() { @Override public String call() throws Exception { return null; } }); try { if (result.isDone()) result.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } pool.shutdown();其它线程池
Executors.newCachedThreadPool(); Executors.newFixedThreadPool(5); Executors.newSingleThreadExecutor();
Executors.newScheduledThreadPool(5); Executors.newSingleThreadScheduledExecutor();
Executors.newWorkStealingPool(Runtime.getRuntime().availableProcessors()); Executors.newWorkStealingPool();
ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)int corePoolSize : 核心线程数
int maximumPoolSize : 最大线程数
long keepAliveTime, TimeUnit unit : 非核心线程闲置的超时时间(超时将被回收)
executor.allowCoreThreadTimeOut(true); // 可将超时同时作用到核心线程
BlockingQueue<Runnable> workQueue : 任务队列
ThreadFactory threadFactory : 线程工厂
RejectedExecutionHandler handler : 饱和策略
new ThreadPoolExecutor.AbortPolicy(); // 抛出异常(默认) new ThreadPoolExecutor.CallerRunsPolicy(); // 用调用者所在线程处理 new ThreadPoolExecutor.DiscardPolicy(); // 丢弃新任务 new ThreadPoolExecutor.DiscardOldestPolicy(); // 挤掉一个任务
示例用法
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 50, 5, TimeUnit.SECONDS, new ArrayBlockingQueue(5), new ThreadPoolExecutor.DiscardOldestPolicy());线程池默认是空的(可调用 prestartAllCoreThreads 提前启动核心线程),若持续有任务进来,会先填满 5 个核心线程,然后进任务队列,任务队列满了,会继续创建线程直到 50 个,再然后会执行饱和策略
ForkJoinPool 用于分解任务
一般用法
public class PrintTask extends RecursiveAction { private int start, end; public PrintTask(int start, int end) { this.start = start; this.end = end; } @Override protected void compute() { if (end - start < 50) { for (int i = start; i < end; i++) { LOG.v(Thread.currentThread().getName() + " - " + i); } } else { int middle = (start + end) / 2; PrintTask left = new PrintTask(start, middle); PrintTask right = new PrintTask(middle, end); left.fork(); right.fork(); } } } 调用示例 ForkJoinPool pool = new ForkJoinPool(); pool.submit(new PrintTask(0, 300)); pool.shutdown();带返回值的用法
public class PrintTask extends RecursiveTask<Integer> { private int start, end; public PrintTask(int start, int end) { this.start = start; this.end = end; } @Override protected Integer compute() { int sum = 0; if (end - start < 50) { for (int i = start; i < end; i++) { sum += i; } } else { int middle = (start + end) / 2; PrintTask left = new PrintTask(start, middle); PrintTask right = new PrintTask(middle, end); left.fork(); right.fork(); sum = left.join() + right.join(); } return sum; } } 调用示例 ForkJoinPool pool = new ForkJoinPool(); ForkJoinTask<Integer> result = pool.submit(new PrintTask(0, 300)); try { LOG.v("result : " + result.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } pool.shutdown();ThreadLocal 用于为每个线程生成数据副本
private ThreadLocal<String> data = new ThreadLocal<>(); public void func() { data.get(); data.set("some"); }将集合包装为线程安全系列方法
Collections.synchronizedXxx()
