生产者和消费者
package com.sdut.day4;
class Resource1
{
private Stringname;
privateintcount = 1;
booleanflag =false;
publicsynchronized void set(String name)
{
while(flag)
{
try {
this.wait();
}catch (InterruptedException e){
//TODO Auto-generated catchblock
e.printStackTrace();
}
}
this.name = name+count;
count++;
System.out.println(Thread.class.getName()+"生产者"+this.name);
flag =true;
this.notifyAll();
}
publicsynchronizedvoid out()
{
while(!flag)//while判断标记,解决了线程获取执行权后,是否要执行
{
try {
this.wait();
}catch (InterruptedException e){
//TODO Auto-generated catchblock
e.printStackTrace();
}
}
System.out.println(Thread.class.getName()+"------------消费者"+this.name);
flag =false;
this.notifyAll();//解决了,本方线程一定会唤醒对方线程
}
}
class Producerimplements Runnable
{
private Resource1 r ;
Producer(Resource1 r)
{
this.r = r;
}
publicvoid run()
{
while(true)
{
r.set("烤鸭");
}
}
}
class Consumerimplements Runnable
{
private Resource1r ;
Consumer(Resource1 r)
{
this.r = r;
}
publicvoid run()
{
while(true)
{
r.out();
}
}
}
publicclass ProducerConsumer {
publicstaticvoid main(String[] args) {
Resource1r =new Resource1();
Producerp1 =new Producer(r);
Consumerc1 =new Consumer(r);
Thread t0=new Thread(p1);
Thread t1=new Thread(p1);
Thread t2=new Thread(c1);
Thread t3=new Thread(c1);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
Lock 和 Condition
自从jdk1.5以后将同步和锁封装成了对象,并将操作锁的隐士方式变成了显式
Lock lock = new ReentrantLock();
Void show
{
Lock.lock();//获取锁
Code….
Lock.unlock();//释放锁常常放在finally里面
}
package com.sdut.day4;
importjava.util.concurrent.locks.Condition;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
class Resource1
{
private Stringname;
privateintcount = 1;
booleanflag =false;
Lock lock1 = new ReentrantLock();//创建一个锁对象。替代了同步代码块
//通过已有的锁对象来获取该锁上的监视器对象
//锁和监视器分离。设置一个锁,不同的监视器
Condition con1 = lock1.newCondition();//生产者的监视器
Condition con2 = lock1.newCondition();//消费者的监视器
public void set(String name)
{
try{
lock1.lock();
while(flag)
{
try {
con1.await();
}catch (InterruptedException e){
//TODO Auto-generated catchblock
e.printStackTrace();
}
}
this.name = name+count;
count++;
System.out.println(Thread.class.getName()+"生产者"+this.name);
flag = true;
con2. signal ();//唤醒所有处于该监视下的线程
}
finally
{
lock1.unlock();
}
}
public void out()
{
try
{
lock1.lock();
while(!flag)//while判断标记,解决了线程获取执行权后,是否要执行
{
try {
con2.await();
}catch (InterruptedException e){
//TODO Auto-generated catchblock
e.printStackTrace();
}
}
System.out.println(Thread.class.getName()+"------------消费者"+this.name);
flag =false;
con1. signal ();//解决了,本方线程一定会唤醒对方线程
}
finally
{
lock1.unlock();
}
}
}
class Producerimplements Runnable
{
private Resource1 r ;
Producer(Resource1 r)
{
this.r = r;
}
publicvoid run()
{
while(true)
{
r.set("烤鸭");
}
}
}
class Consumerimplements Runnable
{
private Resource1r ;
Consumer( Resource1r)
{
this.r = r;
}
publicvoid run()
{
while(true)
{
r.out();
}
}
}
publicclass ProducerConsumer {
publicstaticvoid main(String[] args) {
Resource1r =new Resource1();
Producerp1 =new Producer(r);
Consumerc1 =new Consumer(r);
Thread t0=new Thread(p1);
Thread t1=new Thread(p1);
Thread t2=new Thread(c1);
Threadt3=new Thread(c1);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
Wait和sleep区别
1. wait可以指定时间也可以不指定,sleep必须指定时间
2. 在同步中,对cpu的执行权和锁的处理不同
Wait:释放执行权,并且释放锁。
Sleep:释放执行权,但是不释放锁
同步里面活着的线程可以不止一个,但是执行的只有一个,谁有锁谁执行
如何停止线程
任务中都会有循环结构,只要控制住循环就可以结束任务,可以使用标志
可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态钟来,让cpu具备执行资格
当强制制动会发生InterruptedException ,记着处理
SetDaemon(true) :后台线程,在线程开启之前定义线程为后台线程,如果所有前台线程都消失,则后台线程也跟着消失,
Join();进程要申请加入进来,运行。主线程要把资格释放出来
等到某个Join()的线程结束后,才能开始执行
例如:t1.start() t2.start() t1.join()则主线程需要等到t1线程运行结束后才能继续运行。
ToString():
线程的优先级:t2.setPriority(Thread.Max_PRIORITY)
Yield()
使用匿名类创建线程:
new Thread()
{
publicvoid run()
{
for(inti = 0 ;i < 20 ;i++){
}
}
}.start();
new Thread(
newrunnabel()
{
publicvoid run()
{
for(int i = 0 ;i<30 ;i++)
{
}
}
}
)
面试题:
class Test implements Runnable
{
publicvoid run(Thread r)
{
}
}
该题会发生错误,错误出现在首行,因为没有实现Runnable这个借口的默认方法run(),应该被abstract修饰
class ThreadTest
{
publicThread(
newRunnable()
{
publicvoid run()
{
System.out.println("runnablerun");
}
}
)
{
publicvoid run()
{
System.out.println("subThreadrun");
}
}
}
该题会打印,打印结果是subThread run因为,虽然runnable的子对象复写了Thread的默认的run方法,但是
Thread 的子类又覆盖了父类的run方法,所有最终打印的是子类的run方法