多线程补充
继承Thread类与实现Runnable接口两种创建多线程方式的对比:
开发中:优先选择:实现Runnable接口的方式
原因:
1. 实现Runnable接口的方式没类的单继承性的局限性
2. 实现的方式更适合来处理多个线程共享数据的情况。
相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中。
目前两种方式,要想启动线程,都是调用的Thread类中的start()。
Thread类中其他方法:
1.setname() :设置线程名字,可以通过对象调用方法设置,也可以通过构造器设置
2.yield():释放当前CPU的执行
3.join():在一个线程中调用另一个线程的join()方法时,现有线程进行阻塞状态,待执行结束另一个线程后再执行此线程。
4.stop():强制结束当前线程
5.sleep(long millitime):设置延迟时间(睡眠),例如每隔1s执行一下
6.isAlive():判断当前线程是否存活
线程的优先级
1.
MAX_PRIORITY:10
MIN _PRIORITY:1
NORM_PRIORITY:5 ---> 默认优先级
2.
getpriority():获取当前线程的优先级
setpriority():设置当前线程的优先级(对象调方法)
说明:高优先级的线程要抢占低优先级线程cpu的执行权。但是只是从概率上讲,高优先级的线程高概率的情况下被执行。并不意味着只当高优先级的线程执行完以后,低优先级的线程才执行。
线程通信问题:
在此举例:两线程交替打印1-100的数字
class Communication implements Runnable { int i = 1; public void run() { while (true) { synchronized (this) { notify(); if (i <= 100) { System.out.println(Thread.currentThread().getName() + ":" + i++); } else break; try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
1.线程通信涉及到的三个方法:
wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个。
notifyAll():一旦执行此方法,就会唤醒所有被wait的线程。
2.说明:
1.wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中。
2.wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器。否则,会出现IllegalMonitorStateException异常
3.wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中。
经典案例:生产者消费者问题
class seller{//店员 共享数据 private int total=0; public synchronized void produceProductor() {//生产产品 if (total < 20 ){ total++; System.out.println(Thread.currentThread().getName() + ":开始生产第" + total + "个产品"); notify(); }else { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void consumProduct() { if (total>0){ System.out.println(Thread.currentThread().getName() + ":开始消费第" + total + "个产品"); total--; notify(); }else { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Productor extends Thread{//生产者 private seller se; public Productor(seller se) { this.se = se; } @Override public void run() { System.out.println(getName()+":开始生产产品"); while (true){ se.produceProductor(); } } } class Consum extends Thread{//消费者 private seller se; public Consum(seller se) { this.se = se; } @Override public void run() { System.out.println(getName()+":开始消费产品"); while (true){ se.consumProduct(); } } } public class MyProduct { public static void main(String[] args) { seller s=new seller(); Productor p1=new Productor(s); p1.setName("生产者"); Consum c1=new Consum(s); Consum c2=new Consum(s); c1.setName("消费者1"); c2.setName("消费者2"); p1.start(); c1.start(); } }