黑马程序员 java多线程笔记(二)

-------android培训 、java培训、期待与您交流! ----------

线程间通信 

其实就是多个线程在操作同一个资源但是操作的总舵不同,(采用单例设计模式可以保证资源位置)

加了同步后还不安全 要想到同步的前提条件(1 是不是两个以上的线程2是不是多线程使用同一个锁)

wait()和sleep()的区别

wait()是释放资源 释放锁

线程间通信示例代码


sleep() 释放资源 不释放锁

wait() notify() notifyAll() 都是用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有同步才具有锁。

为什么这些操作线程的方法都要定义在object类中呢,

因为这些方法在操作同步线程时,都必须要表示他们所操作线程只有锁,只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒,不可以对不同锁上的线程进行唤醒,也就是说等待和唤醒必须是同一个锁,而锁可以是任意对象,而可以被任意对象都调用的方法定义在object中。

下列程序按 ctrl + C结束。

class Res
{
	String name;
	String sex;
	boolean flag = false; 
}
class Input implements Runnable
{
	private Res r;
	Input(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			synchronized(r)//多线程间通信 解决完全问题
			{
				if (r.flag)
				{
					try
					{
						r.wait(); //制造等待唤醒机制
					}
					catch (Exception e)
					{
					}
					if (x==0)
					{
						r.name="mike";
						r.sex="man";
					}
					else
					{
						r.name="lili";
						r.sex="woman";
					}
					x = (x+1)%2;
					r.flag = true;
					r.notify();//唤醒

				}
			}
		}
	}
}
class  Output implements Runnable
{
	private Res r;
	Output(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while (true)
		{
			synchronized(r)
			{
				if (!r.flag)
				{
					try
					{
						r.wait();
					}
					catch (Exception e)
					{
					}
					System.out.println(r.name+"......"+r.sex);
					r.flag = false;
					r.notify();
				}
			}
		}
	}
}
class  InputOutputDemo
{
	public static void main(String[] args) 
	{
		Res r = new Res();
		Input in = new Input(r);
		Output out = new Output(r);

		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);

		t1.start();
		t2.start();
	
	}
}

jdk1.5中提供了多线程升级解决方案将同步的synchronized替换成现实的lock操作,将Object中的wait notify notifyAll替换了condition对象,该独享一lock锁进行获取 下面是典型的生产者消费者问题,利用到了 升级后的多线程解决方案

运行时按ctrl + c 结束

import java.util.concurrent.locks.*; // 导入包 才能用lock 

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 Consumer implements Runnable
{
	private Resource res;
	Consumer(Resource res)
	{
		this.res = res;
	}
	public void run()
	{
		while (true)
		{
			try
			{
				res.out();
			}
			catch (InterruptedException e)
			{
			}
		}
	}
}
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  PCD
{
	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();

	
	}
}
停止线程,

stop方法已经过时了,如何停止线程只有一种方法 就是run方法结束,开启多线程运行,运行代码通常都是循环结构,只要控制循环就可以让run方法结束,也就是线程结束。 特殊情况 当线程处于了冻结状态就不会读取到标记,那么线程就不会结束。 interrupt将处于冻结状态的线程,强制到运行状态中来,只有运行才能标记,interrupt是清楚线程的冻结状态

当没有指定的方式让冻结状态复活到运行状态是,这是需要对冻结状态进行清楚,强制让线程回复到运行状态钟来,这样就可以操作标记让线程结束。 Thread中提供了interrupt()方法。后台线程的特点是开启跟后台线程一起争夺线程资源当所有的前台线程结束后,后台线程会自动结束。 下例子中t1.setDaemon(true);这个方法就是把t1变成后台线程随着主线程的结束 t1自动结束。

class StopThread implements Runnable
{
	private boolean flag = true;
	public void run()
	{
		while (flag)
		{
			System.out.println(Thread.currentThread().getName()+"...run");
		}
	}
	public void changeflag()
	{
		flag = false;
	}
		
}
class  STD
{
	public static void main(String[] args) 
	{
		StopThread st = new StopThread();//开一对象
		Thread t1 = new Thread(st);//开启两个线程
		Thread t2 = new Thread(st);

		t1.setDaemon(true);//变成保护线程 注意此处不要写错字母顺序 是daemon 
		t2.setDaemon(true);
		t1.start();
		t2.start();

		int num  = 0;

		while (true)
		{
			if (num++ == 60)
			{
				break;
			}
			System.out.println(Thread.currentThread().getName()+"...."+num);
		
		}
			
		
		
		System.out.println("over!");
	}
}


join方法

主线程在向下走的时候t1.join()表示 t1要cpu的执行权,这时候执行权在主线程里面,主线程会把执行权释放,此时主线程会处于冻结状态,或者的线程跟t1争夺执行权,有可能是t1跟其他线程交替执行,主线程在t1结束之后才能恢复,无论其他线程如何主线程恢复到运行状态,主线程遇到谁的join就等谁,【谁让主线程等,就等到死】

join的特点

当A线程执行到了B线程的join方法是,A就等待B线程执行完A才会执行。

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

Thread.yield()方法是用来停止当前线程,执行其他线程可以用来平均、平衡执行其他线程,当某些代码需要同时进行的时候可以用不同的线程进行封装。

-------android培训 、java培训、期待与您交流! ----------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值