java 多线程

来源:互联网 发布:xfplay 怎么没有mac版 编辑:程序博客网 时间:2024/06/02 04:21



线程的状态:被创建(new PrimeThread())-->运行(start()) ----sleep(time)| wait()[notify()  唤醒等待的线程]----冻结-----销毁stop()/run方法执行完毕)



创建线程的方式:实现方式,继承方式

实现方式 : 避免了多继承的弊端


同步 

条件、前提:

    1、必须要有两个或者两个以上的线程

    2、必须是多个线程使用同一个锁

好处:解决了安全问题

弊端:多个现象需要判断锁,比较消耗资源

什么时候同步,什么时候不同步

1、明确那些代码是多线程运行代码

2、明确共享数据

3、明确多线程运行代码中那些语句是操作共享数据的

静态方法被同步使用的锁是: 该方法所在类的字节码对象

非静态方法被同步使用的锁是:this

等待唤醒机制

wait()notify()、 notifyAll()

都使用在同步中,因为要对持有监视器(锁)的线程操作。

所以要使用在同步中,因为只有同步才具有锁。

等待和唤醒 必须是同一个锁对象调用

为什么这些操作线程的方法要定义在Object类中呢?

因为,监视器(锁)是任意对象,所以可以被任意对象调用



线程间的通信


案例需求:

一个生产者,一个消费者。生产者生产一个,消费者消费一个

传统的做法(jdk1.5之前的)

class Resource {private String name;private int count ;boolean hasVal = false;//判断是否有数据/** * 模拟生产方法 * @param name */public synchronized void set(String name){while(hasVal)///当醒来的时候  还要判断  是不是已经有数据 try {this.wait();} catch (Exception e) {}//如果判断 生产的东西已经被消费了,就继续生产System.out.println(Thread.currentThread().getName()+"生产者---------"+ this.count);this.name = name +"---" + count++;this.hasVal = true;this.notifyAll();}/** * 模拟消费方法 */public synchronized void out(){while(!hasVal) //当醒来的时候  还要判断  是不是已经有数据 try {this.wait();} catch (Exception e) {}//如果有数据(代表已经生产了一个) 就打印出来this.hasVal = false;this.notifyAll();System.out.println(Thread.currentThread().getName()+"消费者---------"+ this.name);}} //生产 的类class Producer implements Runnable{private Resource res;Producer (Resource res){this.res = res;}@Overridepublic void run() {while(true)res.set("苹果");}}//消费类class Customer implements Runnable{private Resource res;Customer (Resource res){this.res = res;}@Overridepublic void run() {while(true)res.out();}}


 

新做法--推荐(jdk1.5之后)

需求还是一样,思想也还是一样

class Resource1 {private String name ;private String sex;private boolean flag = false;//判断是否有数据private final Lock lock = new ReentrantLock();//Condition  可以理解为 同步的对象锁(以前是用 Object对象)private final Condition  cond_pro = lock.newCondition();private final Condition  cond_cus = lock.newCondition();public void set(String name ,String sex) throws InterruptedException{lock.lock();///此处是关键部分, 使用了面向对象的方式try {while(flag){cond_pro.await();}//让生产线程等待this.name = name;this.sex = sex;this.flag = true;cond_cus.signalAll();//唤醒  消费线程} finally {lock.unlock();//此处是关键部分,关闭锁资源}}public void out () throws InterruptedException{lock.lock();try {while(!flag){cond_cus.await();}System.out.println(this.name+"***"+this.sex);this.flag = false;cond_pro.signalAll();} finally {lock.unlock();}}}



停止线程

jdk1.5之后,就没有提供 ,手动停止线程的方法。所以停止线程的方法唯一方法就是: 让run方法执行完毕

而在大多数run方法中都使用了循环,所以只要控制循环就可以控制线程了。

特殊情况:

在被同步的run方法中,或者 run方法中的一个同步方法 中 使用了wait()方法,而同步代码块中也没有唤醒当前锁的方法是,线程就会一直处于 冻结状态,此时可以使用Thread.interrupt()方法来唤醒处于冻结状态的线程,让他们有执行线程的资格,

class StopThreadSync implements Runnable{private boolean flag = true;@Overridepublic synchronized void run() {while(flag){try {///处于冻结状态,放弃了执行资格 ,而且没有  锁 来唤醒当前线程wait();} catch (InterruptedException e) {System.out.println("interrupt Exception");//当打断 处于冻结状态的 线程(此时当前线程 有了执行资格),会抛出异常  ,//flag =false;}System.out.println("Thread   Runing...");}}public void stopWhile (){this.flag = false;}}


守护线程

Thread.setDaemon(boolean);

将该线程标记为守护线程(有点类似 后台线程),当正在运行的所有线程都是守护(后台)线程时,java虚拟机退出(即程序结束)

注意:这个方法必须在线程运行前执行

 

 

Join 等待线程

这个方法能抢夺cpu执行权,

ThreadDemo td = new ThreadDemo();///Runnble子类

Thread t1 = new Thread(td );

Thread t1 = new Thread(td );

t2.start();

////主线程会等待 t1线程执行完毕后,才开始执行,跟其他线程是否执行完毕没有关系

t1.join();

t1.start();

线程的优先级

ThreadDemo td = new ThreadDemo();///Runnble子类

Thread t1 = new Thread(td );

Thread t1 = new Thread(td );

t2.start();

////提高t1抢夺cpu执行权的频率

t1.setPriority(Thread.MAX_PRIORITY);

t1.start();



0 0
原创粉丝点击