1.2、JDK1.5多线程新特性
JDK1.5新特性,针对全部唤醒机制导致本方被唤醒存在的隐患进行了修正。(锁的组合使用)
它其实就是一个替代品: 把隐式的锁改为显示的锁,可以人为操纵。
- synchronized-->Lock:通过创建对象获得, Lock lock = new ReentrantLock();
- lock.lock();//同步,加锁
- lock.unlock();//释放锁
- Condition condition = lock.newCondition();//Lock中的newCondition()返回的是一个Condition的对象。
Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,
为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
- notify() --> sigle();
- notifyAll() --> sigleAll()
- wait() --> await();
下面是多线程新特性的使用实例:
public class ProducerConsumerDemo { public static void main(String[] args) { Resource res = new Resource(); Producer pro = new Producer(res); Consumer con = new Consumer(res); Thread t1 = new Thread(pro); Thread t2 = new Thread(pro); Thread t3 = new Thread(con); Thread t4 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); } } class Resource { private String name; private int count = 1; private boolean flag = false; private Lock lock = new ReentrantLock(); private Condition condition_pro = lock.newCondition(); private Condition condition_con = lock.newCondition(); public void set(String name) throws InterruptedException { lock.lock(); try { while (flag) condition_pro.await(); this.name = name + "--" + count++; System.out.println(Thread.currentThread().getName() + "...生产者.." + this.name); flag = true; condition_con.signal(); } finally { lock.unlock();// 释放锁的动作一定要执行。 } } public void out() throws InterruptedException { lock.lock(); try { while (!flag) condition_con.await(); System.out.println(Thread.currentThread().getName()+ "...消费者........." + this.name); flag = false; condition_pro.signal(); } finally { lock.unlock(); } } } // 生产者 class Producer implements Runnable { private Resource res; Producer(Resource res) { this.res = res; } public void run() { while (true) { try {res.set("+商品+");} catch (InterruptedException e) {} } } } // 消费者 class Consumer implements Runnable { private Resource res; Consumer(Resource res) { this.res = res; } public void run() { while (true) { try {res.out();} catch (InterruptedException e) {} } } }
释放锁的操作一定要执行,一般放在异常处理时的finally中。由于处理await()时会出现异常,所以导致程序无法执行到释放锁的操作,所以我们必须将释放锁操作放在finally中。
针对全部唤醒机制导致本方被唤醒存在的隐患进行了修正:一个Lock可以对应多个Condition对象。我们可以通过多个对象来达到唤醒某个具体的线程 。
如果我们想要停止线程,stop()方法已经过时,我们可以定义循环结束标记来停止线程。
class StopThread implements Runnable { public void run() { System.out.println(Thread.currentThread().getName() + "....run"); } } public class StopThreadDemo { public static void main(String[] args) { StopThread st = new StopThread(); Thread t1 = new Thread(st); Thread t2 = new Thread(st); t1.start(); t2.start(); int num = 0; while (true) { if (num++ == 60) { break; } System.out.println(Thread.currentThread().getName() + "......."+ num); } } }
线程中还提供下面等一系列方法来对线程进行操作:
- interrupt()方法来中断线程,该方法是结束线程的冻结状态,使线程回到运行状态中来。
- setDaemon(boolean):将线程标记为守护线程或用户线程。其实守护线程就是后台线程,而主线程是前台线程,当前台线程结束,后台线程也跟着结束。
- join():加入线程,当A线程执行到了B线程的join()方法时,A线程就会等待,等B线程执行完,A线程才会执行。join可以用来临时加入线程执行。
a 多线程优先级:
所有线程默认的优先级是5,我们想改变优先级可以通过一个方法:优先级越高抢到cpu执行权的机会越多。
void setPriority(优先级):对应三个常量值
- MAX_PRIORITY :10
- MIN_PRIORITY :0
- NORM_PRIORITY :5
Thread类中重写了Object中的toString()方法,可以打印线程名称,线程组和线程优先级。
yield()方法:暂停当前正在执行的线程对象,并执行其他线程。它是一个静态方法,减缓调用这个方法的线程占用过多执行权。