线程池
- 多任务与线程池
- 线程池是开发执行很多任务的理想方法
- 线程池管理有限数目的线程
- 使用Executor接口在线程池中执行任务
import java.util.concurrent.*;
public class Executordemo{
public static void main(String[] args) {
//固定线程数量的线程池 创建
ExecutorService executor = Executors.
newFixedThreadPool(3);
//将任务提交到线程池执行
executor.execute(new PrintChar('a', 50));
executor.execute(new PrintChar('b', 50));
//executor.execute(new PrintNum(100));
executor.shutdown();
}
}
注意:Executors.newCachedThreadPool();
线程同步
import java.util.concurrent.*;
public class AccountWithoutSync{
private static Account account = new Account();
public static void main(String[] args){
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
executor.execute(new AddAPennyThread());
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("What is balance ? " + account.getBalance());
}
static class AddAPennyThread implements Runnable {
public void run() {
account.deposit(1);
}
}
}
class Account {
private int balance = 0;
public int getBalance() {
return balance;
}
public void deposit(int amount) {
int newBalance = balance + amount;
try {
Thread.sleep(1);
}catch (InterruptedException ex) {
}
balance = newBalance;
}
}
//What is balance ? 3
Synchronized关键字
- 用于解决资源使用混乱问题
- 确保一次只有一个线程可以访问指定资源
- 例如:
public synchronized void deposit(double amount)
- 这样在线程1执行deposit的时候,account对象被锁住
- 线程2只能等待account被解锁后在执行deposit
- 该关键字还可以修饰代码块,称为同步语句。此处如果account对象处于被引用(被其他线程锁定)状态,则当前线程等待account解锁。
synchronized (account){
account.deposit(1);
}
避免死锁
使用synchronized锁定对象很可能导致死锁。
**解决办法:**资源排序
给每个需要锁定的对象事先进行排序,线程锁定对象时必须按顺序锁定。
线程的状态
- 新建
相关方法:start() - 就绪
相关方法:Yield() - 运行
相关方法:start() - 阻塞
相关方法:join,sleep,wait,lock - 结束
相关方法:run()执行完毕
同步集合
Java集合框架中的类不是线程安全的。
通过Synchronization wrapper的六个静态方法来将集合转成同步版本。
常用的:调用synchronizedCollection(Collection c)返回一个新的collection对象,它包含的所有方法都加了synchronized关键字。