黑马程序员_学习笔记第12天——多线程2

本文深入探讨了ASP.NET、Android、iOS开发技术,分享了.Net培训经验,介绍了线程同步、优先级、守护线程、join方法、中断线程等关键概念。同时,提供了代码示例,帮助开发者提升技能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

---------------------- ASP.Net+Android+IOS开发、 href="http://edu.youkuaiyun.com"target="blank">.Net培训、期待与您交流! ----------------------

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

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

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

public class InputOutDemo {

	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();
		*/
		new Thread(new Input(r)).start();
		new Thread(new Output(r)).start();
	}

}
class Res { 
	private String name;
	private String sex;
	private boolean flag = false;
	
	public synchronized void set(String name,String sex) {
		if(flag)
			try {this.wait();}catch (Exception e) {}
		this.name = name;
		this.sex = sex;
		flag = true;
		this.notify();
	}
	public synchronized void out(){
		if(!flag)
			try {this.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;
	}
	int x ;
	
	public void run() {
		while(true) {
			/*synchronized(r){
				if(r.flag)
					try {r.wait();}catch (Exception e) {}*/
				if(x==0){
					r.set("mike","man");
				}
				else{
					r.set("丽丽","女女女女女");
				}
				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();
			}
			*/
			
			r.out();
		}
		
	}
}

3、对于多个生产者和消费者,为什么要定义while判断标记:因为让被唤醒的线程再一次判断标记。

      为什么要定义notifyAll:因为需要唤醒对方线程,因为只用notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。

public class ProducerConsumerDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Resource r = new Resource();
		Producer pro = new Producer(r);
		Consumer con = new Consumer(r);
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(con);
		Thread t3 = new Thread(pro);
		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)
			try {wait();}catch (Exception e) {}
		this.name = name+"--"+count++;
		
		System.out.println(Thread.currentThread().getName()+"........生产者........."+this.name);
		flag = true;
		this.notifyAll();
	}
	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) {
			res.out();
		}
	}
}


4、jdk1.5中提供了多线程升级解决方法,将同步Synchronized替换成了显示的Lock操作,将Object 中的wait,notify,notifyAll,替换成了Condition对象,该对象可以Lock锁,进行获取。该示例中,实现了本方只唤醒对方的操作。

没有Lock之前,一个锁对应一个wait、notify,有了之后,可以对应多个wait、notify

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerConsumerDemo2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Resource2 r = new Resource2();
		Producer2 pro = new Producer2(r);
		Consumer2 con = new Consumer2(r);
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(con);
		Thread t3 = new Thread(pro);
		Thread t4 = new Thread(con);
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}

}
class Resource2 {
	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 synchronized 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 Producer2 implements Runnable {
	private Resource2 res;
	Producer2(Resource2 res) {
		this.res = res;
	}
	public void run() {
		while(true) {
			try{
				res.set("+商品+");
			} catch(InterruptedException e) {
				
			}
			
		}
	}
}

class Consumer2 implements Runnable {
	private Resource2 res;
	Consumer2(Resource2 res) {
		this.res=res;
	}
	public void run() {
		while (true) {
			try {
				res.out();
			}catch(InterruptedException e) {
				
			}
			
		}
	}
}

5、stop方法已经过时,如何停止线程?

只有一种方法,run方法结束。

开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以让run方法结束,也就是线程结束。

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

当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。

Thread类提供该方法interrupt();

public class StopThreadDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		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) {
				//st.changeFlag();
				t1.interrupt();
				t2.interrupt();
				break;
			}
			System.out.println(Thread.currentThread().getName()+"----main-----");
		}
	}

}

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;
	}
	
}

6、守护线程:setDaemon(true);该方法必须放在线程开启(start)之前,当正在运行的线程都是守护线程时,java虚拟机退出。

7、join特点:当A线程执行到了B线程的join()方法时,A就会等待,等B线程都执行完,A才会执行。join可以用来临时加入线程执行。

public class JoinDemo {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub

		Demo d = new Demo();
		
		Thread t1 = new Thread(d);
		Thread t2 = new Thread(d);
		
		t1.start();
		t1.join();
		t2.start();
		
		for(int x=0; x<80 ; x++) {
			System.out.println("main...."+x);
		}
		System.out.println("over");
	}

}
class Demo implements Runnable {
	public void run() {
		for ( int x = 0; x<70; x++) {
			System.out.println(Thread.currentThread().getName()+"..."+x);
		}
	}
}

8、优先级:

设置优先级: t1.setPriority(Thread.MAX_PRIORITY),或MIN_PRIORITY或NORM_PRIORITY,(优先级1-10),正常的都为5级

9、yield()暂停当前正在执行的线程对象,并执行其它线程。Thread.yield()

public class ThreadTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Thread() {
			public void run() {
				for(int x=0; x<100; x++) {
					System.out.println(Thread.currentThread().getName()+"---1");
				}
			}
		}.start();
		
		for(int x=0; x<100; x++) {
			System.out.println(Thread.currentThread()+"----2");
		}
		
		Runnable r = new Runnable() {
			public void run() {
				for(int x=0; x<100; x++) {
					System.out.println(Thread.currentThread()+"----3");
				}
			}
		};
		new Thread(r).start();

	}

}


---------------------- ASP.Net+Android+IOS开发、 href="http://edu.youkuaiyun.com"target="blank">.Net培训、期待与您交流! ----------------------详细请查看: http://edu.youkuaiyun.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值