1.什么是死锁
当一个线程拥有A对象锁标记,并等待B对象锁标记,同时第二个线程拥有B对象锁标记并等待A对象锁标记,产生死锁。
一个线程可以同时拥有多个对象的锁标记,当线程阻塞时,不会释放已经拥有的锁标记,由此可能造成死锁。
public class ZLock {
public static Object l1 = new Object();
public static Object l2 = new Object();
}
public class HTask extends Thread{
@Override
public void run() {
synchronized(l1){
System.out.println("l1在绘画");
synchronized (l2){
System.out.println("l2在素描");
System.out.println("l2执行完成");
}
}
}
}
public class WTask extends Thread {
@Override
public void run() {
synchronized(l2){
System.out.println("l2在绘画");
synchronized (l1){
System.out.println("l1在素描");
System.out.println("l1执行完成");
}
}
}
}
public class ZLockTest {
public static void main(String[] args) throws InterruptedException {
HTask hTask = new HTask();
WTask wTask = new WTask();
hTask.start();
wTask.start();
}
}
解决死锁
public class ZLockTest {
public static void main(String[] args) throws InterruptedException {
HTask hTask = new HTask();
WTask wTask = new WTask();
hTask.start();
//设置休眠时间
Thread.sleep(1000);
wTask.start();
}
}
2. 线程通信
正常情况下,每个子线程完成各自的任务就可以结束了。不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程间通信了。
public class BankCard {
private int balance;//余额
private boolean flag;//true表示卡中有钱,false表示卡中没钱
//存钱方法 并且为方法上锁
public synchronized void save(int money) throws InterruptedException {
if (flag == true) {
//调用wait 当前线程会释放锁资源并进入等待列队。等待列队中的线程需要其他线程调用notity来唤醒参与下次竞争
this.wait();
}
balance = balance + money;
System.out.println(Thread.currentThread().getName() + "往卡中存入了" + money + ";卡中余额为" + balance);
flag = true;
//随机唤醒等待列队中的对象
this.notify();
}
//取钱方法 为方法上锁
public synchronized void take(int money) throws InterruptedException {
if (flag == false){
this.wait();
}
balance = balance - money;
System.out.println(Thread.currentThread().getName() + "从卡中取出了" + money + ";卡中余额为" + balance);
flag = false;
this.notify();
}
}
线程任务取钱
public class TakeTask implements Runnable{
private BankCard bankCard;
public TakeTask(BankCard b){
bankCard = b;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
bankCard.take(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
线程任务存钱
public class SaveTask implements Runnable{
private BankCard bankCard;
public SaveTask(BankCard b){
bankCard = b;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
bankCard.save(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class TestTask {
public static void main(String[] args) {
BankCard bankCard = new BankCard();
SaveTask saveTask = new SaveTask(bankCard);
TakeTask takeTask = new TakeTask(bankCard);
Thread thread = new Thread(saveTask, "存款人");
Thread thread1 = new Thread(takeTask,"取款人");
thread.start();
thread1.start();
}
}
3. 线程的状态
new :新建状态
RUNNABLE:start()就绪状态
BLOCKED:堵塞状态。例如加锁时
WAITING:无期等待。例如调用waid方法时
TIME_WAITING:有期等待。例如调用sleep方法
TERMINATED:终止状态。线程的任务代码执行完毕或出现异常
4. 线程池
线程池的创建
public class XTest {
public static void main(String[] args) {
//设置最多五个等待任务
ArrayBlockingQueue<Runnable> runnables = new ArrayBlockingQueue<Runnable>(5);
//5设置线程个数 ,10设置线程最大个数,3设置空闲的单位时间s
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 3, TimeUnit.SECONDS,runnables);
for (int i = 0; i < 20; i++) {
threadPoolExecutor.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-=-=-=-=-=-=");
}
});
}
}
}
利用工具类创建线程池
//创建固定长度的线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
//创建单一线程池
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
//可变线程池
ExecutorService executorService2 = Executors.newCachedThreadPool();
//创建延迟线程池
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
5. Callable创建线程
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int m = 0;
for (int i = 0; i <= 100; i++) {
m = m + i;
}
return m;
}
}
public class MyCallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Integer> submit = executorService.submit(new MyCallable());
Integer i = submit.get();
System.out.println(i);
executorService.shutdown();
}
}