1. Thread.sleep(long millis): 休眠制定的毫秒数。
2. 实现多线程的两种方法
2.1 实现Runnable接口
class BallRunnable implements Runnable {
public void run() { //需要try..catch来捕获异常
try{
do something
} catch (InterruptedException) {}
}
}
2.2 继承Thread
class MyThread extends Thread {
public void run() {task code}
}
2.3 启动线程
Ball b = new Ball();
panel.add(b);
Runnable r = new BallRunnable(b, panel);
Thread t = new Thread(r);
t.start();
不要调用Thread类或者Runnable对象的run方法,直接调用只会在当前线程中执行任务,并不会启动新线程。
3. 中断线程
JDK1.0 stop() 现在已经被弃用,现在使用interrupt方法来请求终止一个线程,步骤如下:
Thread.currentThread().isInterrupted() //首先取得当前线程,然后调用isInterrupted()来判断给线程是否中断
如果一个线程被阻塞,而调用isInterrupted() ,将会产生InterruptedException异常
void interrupt(): 发送一个中断给一个线程,这个线程的中断状态将为True,如果当前线程被sleep调用,将抛出InterruptedException异常。常在catch(InterruptedException e) {Thread().currentThread().interrupt();}
static boolean interrupted(): 检查当前线程是否被中断,调用它将清除该线程的中断状态
boolean isInterrupted(): 检查线程是否被终止,而不会改变中断状态的值
4. 线程状态
New(新生)、Runnable(可运行)、Blocked(被阻塞)、Dead(死亡)
isAlive(): 如果线程已经启动并还没有被终止,返回true
stop(): 停止线程。方法过时
suspend(): 挂起当前线程的执行过程。方法过时
resume(): 恢复线程。方法过时
join(): 等待直到指定的线程死亡
join(long millis): 等待直到指定的线程死亡或经过制定的毫秒数
5. 线程优先级
线程优先级和系统有密切关系
setPriority(int newPriority): 设置线程优先级。一般有Thread.MIN_PRIORITY(值为1)、NORM_PRIORITY(值为5)、MAX_PRIORITY(值为10)
static void yield(): 导致当前执行线程进入让步状态,如果有优先级不低于此线程的其他线程存在,那么这些线程将被调度。
6. 守护线程
也成为后台线程 t.setDaemon(true); 此方法必须在线程开始之前被调用
7. 线程组
可以把类似的线程加入一个线程组来便于统一操作
String groupName = "myGroup";
ThreadGroup g = new ThreadGroup(groupName);
Thread t = new Thread(g, threadName); //把一个线程加入到g线程组中
g.activeCount(); //查明线程组中是否有线程处于可运行状态
g.interrupt(); //中断线程组中所有的线程
8. 未捕获异常处理器
线程run方法不能抛出任何被检查的异常,所以需要对一个线程安装一个处理器
setDefaultUncaughtExceptionHandler()设置默认处理器,如果不设置,则为null
9. 同步
两种方式,一种同步锁,一种使用Synchronized
9.1 锁对象 - 显示锁
private Lock bankLock = new ReentrantLock();
bankLock.lock();
try {do something;}
finally {bankLock.unlock();}
9.2 条件对象
一个线程进入临界区,发现必须等待满足某个条件才能执行,那么就需要使用一个条件对象来实现。
class Bank {
private Condition sufficentFunds; //定义条件对象
public Bank() {
sufficentFunds = bankLock.newConditon(); //从ReentrantLock对象中New一个Condition对象
}
public void transfer(int from, int to, int amount) {
bankLock.lock(); //开始锁对象
try {
while (acconts[from] < amount)
sufficentFunds.await(); //如果不满足条件,就进入阻塞状态
// transfer funds
sufficentFunds.signalAll(); //解除所有线程的阻塞状态
}
finally {bankLock.unlock();}
}
}
await(): 等价于wait(),线程进入阻塞状态,当锁可获得,线程不能马上解除,直到另外一个线程调用同一条件上的signalAll方法。
signalAll(): 等价于notifyAll(),解除阻塞状态,但是线程不会马上执行,还需要竞争锁。
signal(): 等价于notify(),随机解除等待某个线程的阻塞状态。
9.3 Synchronized
同步方法: Synchronized - 隐式锁
同步块: 对单独代码块进行Synchronized
同步实例域: volatile
public boolean isDone() {return done;}
private volatile boolean done;
10. 锁
10.1 死锁
10.2 公平锁
Lock fairLock = new ReentrantLock(true);
10.3 锁测试
myLock.tryLock(): 尝试获得锁但不会发生阻塞,成功返回true
10.4 读/写锁
private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private Lock readLock = rwl.readLock(); //得到一个读操作可公用锁,排斥所有写操作
private Lock writeLock = rwl.writeLock(); //得到一个写锁,排斥其他的读写操作
11. 阻塞队列
11.1 4种阻塞队列
ArrayBlockingQueue(int capacity)和ArrayBlockingQueue(int capacity, boolean fair): 制定容量和公平性设置的阻塞队列,用来循环数组。
LinkedBlockingQueue()或LinkedBlockingQueue(int capacity): 构建一个无边界或者有容量的阻塞队列,由链表实现。
DelayQueue(): 包含Delayed元素的无界的阻塞时间有限的阻塞队列
Delayed.getDelay(TimeUnit unit): 得到该对象的延迟
PriorityBlockingQueue(): 阻塞优先级队列
11.2 队列方法
add: 添加一个元素,队列满则抛出异常
offer:添加一个元素,如果队列满返回false
put: 添加一个元素,队列满则阻塞
remove: 移除并返回队列头部的元素,队列空抛异常
poll: 移除并返回队列头部的元素,队列空返回null
take: 移除并返回队列头部的元素,队列空则阻塞
element: 返回队列头部的元素,队列空抛异常
peek: 返回队列头部的元素,队列空返回null
12. 线程安全的集合
java.uti.concurrent提供两个集合: ConcurrentLinkedQueue和ConcurrentHashMap
ConcurrentHashMap.putIfAbsent(K key, V value): 将给定值和键联系起来
ConcurrentHashMap.remove(K key, V value): 移除
ConcurrentHashMap.replace(K key, V oldValue, V newValue): 新的值相关联
13. Callable和Future
13.1 Callable相当于Runnable,但是有返回值
class Counter implements Callable<Integer> {public Integer call()} //定义Callable
13.2 Future用来保存返回的结果
Counter count = new Counter();
FutureTask<Integer> task = new FutureTask(count);
Thread t = new Thread(task);
t.start();
get(): 获取结果
cancel(boolean mayInterrupt): 尝试取消任务运行,如果线程开始且mayInterrupt为true,那么被中断
isCancelled(): 如果任务在完成之前被取消,返回true
isDone(): 任务是否结束
14. 线程池 - 执行器
14.1 线程池的使用
newCachedThreadPool: 创建线程池,如果池中有空闲线程,则使用空闲线程,否则创建新线程
newFixedThreadPool: 包含固定数量线程
newSingleThreadExecutor: 只有一个线程的池,顺序执行
以上3种,实现了ExecutorService接口。
1. 调用Executors类中静态的newCachedThreadPool或newFixedThreadPool方法
ExecutorService pool = Executors.newCachedThreadPool();
2. 调用submit来提交一个Runnable或Callable对象
MatchCounter counter = new MatchCounter(new File(directory), keyword, pool); //MatchCounter是实现了Callable<Integer>
Future<Integer> result = pool.submit(counter); //提交返回的Callable对象
3. 如果希望取消任务或者保存结果,那么就需要保存好Future对象
result.get();
4. 当不想提交任务的时候调用shutdown
pool.shutdown();
5. 得到线程池容量
int ((ThreadPoolExecutor)pool).getLargestSize();
14.2 预订执行
newScheduledThreadPool: 为预定执行而构建的固定线程池
newSingleThreadScheduledExcutor: 为预定执行而构建的单线程“池”
以上2种,实现了ScheduledExecutorService接口
14.3 控制线程组 - 把所有任务集中起来处理
ArrayList<Callable<Integer>> tasks = ...;
List<Future<Integer>> results = executor.invokeAll(tasks);
15. 同步器