线程休眠方法-static void sleep yield 当前线程让出cpu-参与下次的竞争 jion插入的线程执行完毕后,当前线程才会执行。 setDaemon()设置线程为守护线程.当所有线程执行完毕后,守护线程也会终止。先设置后开始,否则失败 解决线程安全问题 什么情况下会出现线程安全问题?当多个线程操作同一个资源时,则出现线程安全问题。 java如何解决线程安全问题?提供了两种方式:第一种:使用synchronized自动锁 第二种: 使用Lock手动锁。使用锁相对于把原来的异步转换为同步操作。3.使用synchronized关键字解决。它可以使用在方法上,也可以使用在代码块中。synchronized(共享锁对象){同步代码块} Lock它是一个接口,它的实现类是ReentrantLock synchronized使用在方法那么它的共享锁为this syn和lock区别 syn可以使用代码块和方法。自动加锁和释放锁。不会出现死锁问题。 lock它只能使用在代码块中。需要手动加锁和释放锁。如果不释放锁,死锁问题。灵活。它的释放锁必须放在finally. 死锁 线程A拥有锁资源a,希望获取锁资源b,线程B拥有锁资源b,希望获取锁资源a。 两个线程互相拥有对方希望获取的锁资源。可能会出现程序堵塞。从而造成死锁。 解决: 1. 不要使用锁嵌套。 2. 设置超时时间。--Lock类中tryLock. 3. 使用安全java.util.concurrent下的类。 线程状态 NEW,====新建状态。 RUNNABLE,===>就绪状态和运行状态 BLOCKED,===>堵塞状态 WAITING,====>等待状态 TIMED_WAITING,===>限时等待 TERMINATED;===终止。 转换图 wait和sleep方法区别 1. wait来自于Object。sleep来自于Thread 2. wait必须放入同步代码块中,sleep可以在任何地方执行。 3. wait会释放锁资源。sleep不会释放锁。 4. wait需要手动唤醒。sleep时间到了自动唤醒。 长单词释义:来源:Etymonline - Online Etymology Dictionary
1、await是及物动词,可直接接sb./sth.作宾语;wait通常作不及物动词,可与for,to,until等词一起使用。
2、await后面的对象较抽象,例如reply,announcement,arrival等;wait后的对象通常是具体的人或物。
3、wait在日常口语中的运用较多,await用于书面,正式的场合中。
synchronized同步的 syn-一起,共同地;相似地;同时together with, jointly; alike; at the same time。“时间”chrono-。 reentrant re-entrant 可重入;可再入的;可重入的 deposit de-position 存款 de- down, down from, from, off; concerning从……向下、离开、远离”,比喻意义上是“由于……原因、根据” withdraw 取款 卖票 /*MyThread t1=new MyThread(); t1.start(); MyThread t2=new MyThread(); t2.setDaemon(true); t2.start(); System.out.println("main线程执行"+Thread.currentThread().getName()); t1.yield(); t1.join(); for (int i = 0; i < 10; i++) { System.out.println("main线程执行"+i); }*/
使用synchronized自动锁
private int ticket = 100; private static Object obj = new Object(); @Override public void run() { while(true){ synchronized (obj){ if(ticket>0){ System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket+"张票"); ticket--; }else{ break; } } } } public synchronized void sell(){ if(ticket>0){ System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket+"张票"); ticket--; } }
lock手动锁
private int ticket = 100; private Lock lock = new ReentrantLock(); @Override public void run() { while (true){ try { lock.lock(); if (ticket > 0){ System.out.println(Thread.currentThread().getName()+"正在出售第"+ticket+"张票"); ticket--; } else {break;} }finally { lock.unlock(); } } }
线程通信
多线程实现一加一减。余额示例
private Double balance; private boolean isFull; /*满了才能取,空了才能存。设定是一次就能取完*/ public synchronized void deposit(Double amount) throws InterruptedException { if (isFull){ wait(); } balance += amount; isFull = true; notifyAll(); System.out.println( Thread.currentThread().getName() + "存入" + amount + ",余额:" + balance); } public synchronized void withdraw(Double amount) throws InterruptedException { if (!isFull){ wait(); } balance -= amount; isFull = false; notifyAll(); System.out.println( Thread.currentThread().getName() + "取出" + amount + ",余额:" + balance); }
public class CunThread extends Thread{
private BankCard bankCard;
public CunThread(BankCard bankCard){
this.bankCard=bankCard;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
bankCard.deposit(1000);
}
}
}
public class QuThread extends Thread{
private BankCard bankCard;
public QuThread(BankCard bankCard){
this.bankCard=bankCard;
}
@Override
public void run() {
for (int i = 0; i <10 ; i++) {
bankCard.withdraw(1000);
}
}
}
public static void main(String[] args) {
BankCard bankCard=new BankCard();
CunThread c=new CunThread(bankCard);
c.setName("李晨");
QuThread q=new QuThread(bankCard);
q.setName("范冰冰");
c.start();
q.start();
}