您的位置:首页 > 职场人生

黑马程序员--- 学习笔记(第十二天

2014-04-06 12:44 423 查看
 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————

多线程之间的通信
其实就是多线程在操作同一资源,但是操作的动作不同

/*
多线程之间的通信

一个线程负责写,一个线程负责读

*/
class Demo
{
public static void main(String[] args)
{
Resource r=new Resource();
new Thread(new WriterThread(r)).start();
new Thread(new ReaderThread(r)).start();
}
}
/*操作共同的资源*/
class Resource
{
private String name;
private String sex;
private boolean flag=true;
public void setFlag(boolean flag){
this.flag=flag;
}
public synchronized void setInfo(String name,String sex){
while(flag){ //每次都判断标记
try
{
wait();
}
catch (InterruptedException e)
{
}
}
this.name=name;
this.sex=sex;
flag=true;
notifyAll();
}
public synchronized void getInfo(){
while(!flag){
try
{
wait();
}
catch (InterruptedException e)
{
}
}
System.out.println(name+"-----"+sex);
flag=false;
notifyAll();
}

}
/*写入线程*/
class WriterThread implements Runnable
{
private Resource r;
public WriterThread(Resource r){
this.r=r;
}
public void run(){
int i=0;
while(true){
if(i%2==0){
r.setInfo("track","man");
}else{
r.setInfo("赖海娟","女");
}
i++;
}
}

}
/*读取线程*/
class ReaderThread  implements Runnable
{
private Resource r;
public ReaderThread(Resource r){
this.r=r;
}
public void run(){
while(true){
r.getInfo();
}
}
}


wait();

notify();

notifyAll();

都使用在同步中,因为要对持有监视器的线程操作,所以都要使用在

同步中,因为只有同步才具有监视器

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

因为这些方法在操作同步中的线程,都必须要在标识他们的操作线程只有

的锁,只有同一个锁上的被等待线程,可以被同一个锁notify()唤醒,不可以

对不同锁中的线程进行唤醒,也就是说等待和唤醒是同一个锁.

而锁可以使任意对象,所以可以被任意对象调用的方法定义在Object中

一对一生产者,消费者:

/*
生产者,消费者

*/
class Demo1
{
public static void main(String[] args)
{
Resource r=new Resource();
new Thread(new Producer(r)).start();
new Thread(new Consumer(r)).start();
}
}
/*共同所操作的资源*/
class Resource
{
private String ware;
private int count=1;
private boolean b=false;
public  String getWare(){
return ware;
}
public synchronized  void proWare(String ware){
while(b)
try
{
wait();
}
catch (InterruptedException e)
{
}
this.ware=ware+":::"+count++;
b=true;
notifyAll();
}
public synchronized void conWare(){
while(!b)
try
{
wait();
}
catch (InterruptedException e)
{
}
System.out.println("消费--------------"+ware);
b=false;
notifyAll();
}
}
/*生产者*/
class Producer implements Runnable
{
private Resource r;
public Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
r.proWare("商品");
System.out.println("生产-----------"+r.getWare());
}
}
}
/*消费者*/
class Consumer implements Runnable
{
private Resource r;
public Consumer(Resource r){
this.r=r;
}
public void run(){
while(true)
r.conWare();
}
}


对于多个生产者和消费者

为什么要定义while判断标记?

原因:让被唤醒的线程再一次判断标记

/*
生产者 消费者

使用JDK1.5提供的解决方案

只唤醒对方的等待线程
*/
import java.util.concurrent.locks.*;
class Demo2
{
public static void main(String[] args)
{
Resource r=new Resource();

/*两个生产者*/
new Thread(new Producer(r)).start();
new Thread(new Producer(r)).start();

/*两个消费者*/
new Thread(new Consumer(r)).start();
new Thread(new Consumer(r)).start();
}
}
/*共同所操作的资源*/
class Resource
{
private String ware;
private int count=1;
private boolean b=false;
private Lock lock=new ReentrantLock();
private Condition con_pro=lock.newCondition();
private Condition con_con=lock.newCondition();
public  String getWare(){
return ware;
}
public  void proWare(String ware)throws InterruptedException{
lock.lock(); //	获取锁

while(b)
try
{
con_pro.await(); //等待
}
finally
{
lock.unlock();//释放锁
}
this.ware=ware+":::"+count++;
b=true;
con_con.signalAll();//唤醒对方的等待线程
}
public  void conWare()throws InterruptedException{
lock.lock();
while(!b)
try
{
con_con.await();
}
finally
{
lock.unlock();
}
System.out.println(Thread.currentThread().getName()+"消费--------------"+ware);
b=false;
con_pro.signalAll();
}
}
/*生产者*/
class Producer implements Runnable
{
private Resource r;
public Producer(Resource r){
this.r=r;
}
public void run(){
while(true){
try
{
r.proWare("商品");
System.out.println(Thread.currentThread().getName()+"生产-----------"+r.getWare());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
/*消费者*/
class Consumer implements Runnable
{
private Resource r;
public Consumer(Resource r){
this.r=r;
}
public void run(){
while(true){
try{

r.conWare();

}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}


为什么定义notifyAll?

因为需要唤醒的对方线程.因为只用notify,容易出现只唤醒本方线程的

情况,导致程序中的所有程序都在等待.

如何只唤醒对方呢?

需要导包:java.util.concurrent.locks;

JDK1.5中提供了多线程升级解决方法.将同步synchronized替换成显示的Lock

操作. 将Object中的wait,notify,notifyAll替换成Condition对象,该对象

可以通过Lock锁进行获取?

 Lock lock=new ReentrantLock();

 Condition con=lock.newCondition();

在该示例中实现本方只唤醒对方操作?

停止线程

stop方法已经过时?

如何停止线程?只有一种方法就是run方法结束

/*
如何停止线程  清除线程的冻结状态interrupt
*/
class Demo3
{
public static void main(String[] args)
{
Test t=new Test();
Thread tt=new Thread(t);
tt.start();
try
{
Thread.sleep(5000);
tt.interrupt();	//5秒清除线程的冻结状态,重新开始执行
}
catch (Exception e)
{
}
}
}
class Test implements Runnable
{
public synchronized void run(){
for (int i=0;i<100 ;i++ )
{
System.out.println(Thread.currentThread().getName()+"::"+i);
//假如出现wait,则线程冻结  需要清除该状态才可以继续执行
if(i==10)
try
{
wait();
}
catch (InterruptedException  e)
{
e.printStackTrace();
}
}
}

}


开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以 

让run方法结束.也就是线程结束

特殊情况,当线程处于冻结状态,就不会读到标记,那么线程就不会结束

当没有指定的方式让冻结的线程恢复到运行状态,这时需要对冻结进行清除

,强制性制止过程恢复到运行状态中来,这样就可以操作标记让线程结束

Thread类提供了该方法 interrupt();

守护线程:

setDaemon();

将该线程标志为守护线程,或用户线程就是后台线程

必须在启动线程前调用,主线程运行完毕,守护线程机会结束.jvm虚拟机结束

join();

当A线程执行到了B线程的join方法时,就会等待,等b线程执行完毕.

A才会执行

join可以用来临时加入线程执行

toString();

返回线程名称,线程优先级,线程组

ThreadGroup 线程组几乎用不上,就是谁调用该线程,它就属于哪个组,开发不常见

setPriority();//默认优先级是5

MAX_PRIORITY; //最高优先级10

MIN_PRIORITY; //最低优先级1

NORM_PRIORITY;//默认优先级5

yield(); //暂停当前运行线程

当某些代码需要被同时执行时,就等着成线程对象.
开发通常使用Thread的匿名子类或者Runnable的匿名子类

/*
setDaemon守护线程
join临时加入线程
toString//返回线程名称,优先级,线程组
setPriority//设置优先级
yield//暂停线程运行
*/
class Demo4
{
public static void main(String[] args)
{

Thread t1=new Thread(){
public void run(){
for (int i=1;i<=20 ;i++ )
{
System.out.println(Thread.currentThread().toString()+":::"+i);
/*
//当设置为守护线程时,即使wait 主线程运行完 主线程就会结束
if(i==10){
try
{
wait();
}
catch (InterruptedException e)
{
}
}
*/
}
}
};

Runnable r=new Runnable(){
public void run(){
for (int i=1;i<=20 ;i++ )
{
System.out.println(Thread.currentThread().toString()+":::"+i);
/*
//当设置为守护线程时,即使wait 主线程运行完 主线程就会结束
if(i==10){
try
{
wait();
}
catch (InterruptedException e)
{
}
}
*/
}
}
};
Thread t2=new Thread(r);
//t1.setPriority(Thread.MAX_PRIORITY);//设置t1的优先级为10 最大

//t1.setDaemon(true); //设置为守护线程
//t2.setDaemon(true);
t1.start();
t2.start();

t1.yield();	//暂停对当前运行线程 本人经测试 看不出啥  是不是单核电脑的忧桑?
//主线程

for (int i=1;i<=50 ;i++ )
{
System.out.println(Thread.currentThread().toString()+":::"+i);
}

/*
//join();//用来临时加入线程
try
{
t1.join();// 本人经测试 看不出啥  是不是单核电脑的忧桑?
}
catch (Exception e)
{
}
*/
}
}


 —————————— ASP.Net+Android+IOS开发.Net培训、期待与您交流!——————————
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息