创建线程的三种方式
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()