多线程间的通信问题:
线程间的通讯:其实就是多个线程在操作同一个资源,但是操作的动作不同。
线程中的通讯--解决安全问题。
class Res{
private String name;
private String sex;
private boolean flag=false;
public synchronized void set(String name,String sex){
if (flag) {
try{r.wait();}catch(Exception e){}
}
this.name=name;
this.sex=sex;
flag=true;
this.notify();
}
public synchronized void out(){
if (!flag) {
try{r.wait();}catch(Exception e){}
}
System.out.println(name+"........"+sex);
flag=false;
this.notify();
}
}
class Input implements Runnable{
private Res r;
Input(Res r){
this.r=r;
}
public void run(){
int x=0;
while(true){
if (x==0) {
r.set("mike","man");
}
else{
r.set("丽丽","女女女女女");
}
x=(x+1)%2;
}
}
}
class Output implements Runnable{
private Res r;
Output(Res r){
this.r=r;
}
public void run(){
while(true){
r.out();
}
}
}
class InputOutputDemo{
public static void main(String[] args){
Res r=new Res();
new Thread(new Input(r)).start();
new Thread(new Output(r)).start();
/*
Input in=new Input(r);
Output out=new Output(r);
Thread t1=new Thread(in);
Thread t2=new Thread(out);
t1.start();
t2.start();
*/
}
}
wait(),notify(),notifyAll(),都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
为什么这么操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程持有的锁
只有同一个锁上的被等待线程,可以被同一个锁上的notify()唤醒,不可以对
不同锁中的线程进行唤醒。也就是说等待和唤醒必须是同一个锁。而锁可以是
任意对象,所以可以被任意对象调用的方法定义在Object类中。
-----------------------------------------------------------------
线程间的通信-生产者消费者
class ProducerConsumerDemo{
public static void main(String[] args){
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
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;
public synchronized void set(String name){
while(flag) //对于多个生产者和消费者,为什么要定义while判断标记。原因:让被唤醒的线程再一次判断标记。
try{wait();}catch(Exception e){}
this.name=name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag=true;
this.notifyAll();//为什么定义notifyAll,因为需要唤醒对方线程,因为只用notify容易出现只唤醒本方线程的情况,
//导致程序中的所有线程都等待。
}
public synchronized void out(){
while(!flag)
try{wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"...消费者........"+this.name);
flag=false;
this.notifyAll();
}
}
class Producer implements Runnable{
private Resource res;
Producer(Resource res){
this.res=res;
}
public void run{
while(true){
res.set("+商品+");
}
}
}
class Consumer implements Runnable{
private Resource res;
Consumer(Resource res){
this.res=res;
}
public void run(){
while(true){
while(true){
res.out();
}
}
}
}
-----------------------------------------------------------------
生产者消费者JDK 5.0升级版。
import java.util.concurrent.locks.*;
public class ProducerConsumerDemo{
public static void main(String[] args){
Resource r=new Resource();
Producer pro=new Producer(r);
Consumer con=new Consumer(r);
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();
}
}
/*
JDK1.5中提供了多线程升级解决方案。
将同步Syschronized替换成现实Lock操作。
将Object中的wait,notify,notifyAll,替换成了Condition。
该对象可以Lock锁进行获取。
*/
class Resource {
private String name;
private int count = 1;
private boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition_con = lock.newCondition();
private Condition condition_pro = 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) {
}
}
}
}
------------------------------------------------------------------------------------
停止线程:
stop方法已经过时。
如何停止线程?
只有一种,run方法结束。
开启多线程运行,运行代码通常是循环结构。
只要控制住循环,就可以让run方法结束,也就是线程结束。
特殊情况:
当线程处于冻结状态的时候,就不会读取到标志,那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态时,这时候就需要对
冻结状态进行清除。强制让线程恢复到运行状态中来,这时候就可以操作
标记让线程结束。
Thread类中提供了该方法: intterrupt()方法。
class StopThread implements Runnable{
private boolean flag=true;
public synchronized void run(){
while(flag){
try{
wait();
}
catch (InterruptedException e){
System.out.println(Thread.currentThread().getName()+"....Exception");
flag=false;
}
System.out.println(Thread.currentThread().getName()+".....run");
}
}
public void changeFlag(){
flag=false;
}
}
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) {
t1.interrupt();
t2.interrupt();
//st.changeFlag();
break;
}
System.out.println(Thread.currentThread().getName() + "......" + num);
}
System.out.println("over");
}
}
----------------------------------------------------------------
守护线程:可以理解为后台线程。
大多数线程都是前台线程,主线程就是前台线程。
特点是开启后和前台线程共同抢夺CPU的执行权运行。
有一点不同的是当所有的前台线程都结束后,也就是说只有守护线程的时候,
jvm会自动退出,也就是意味着后台线程会自动结束。
Thread t1=new Thread(st);
t1.setDaemon(true);
t1.start();
需要注意的是该方法必须在线程启动前调用。
该方法可以形象的理解为圣斗士星矢守护雅典娜,
如果雅典娜结束,那么他们就结束
---------------------------------------------------------------
join方法:
当A线程执行到了B线程的join方法的时候,A线程让出CPU执行权等待,等B
线程都执行完以后A线程才会执行,join方法可以用来临时进入线程执行
----------------------------------------------------------------