线程(类方法)

本文详细介绍了Java中线程的基本控制方法,包括yield、sleep、join、wait、notify、notifyAll、interrupt和setPriority等。并通过实例演示了如何利用这些方法实现线程间的合作与竞争,例如循环打印字符和实现简单的生产者消费者模型。

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

线程常见的方法:sleep、yield、join、wait、notify、notifyAll、interrupt、setPriority

yield:暂停执行当前线程,并执行其他线程(相同优先级线程更有机会运行)

sleep:休眠,可以让调用它的线程沉睡(停止运行)指定的时间,到了这个时间,线程就会自动醒来,变为可运行状态(RUNNABLE),但这并不表示它马上就会被运行,因为线程调度机制恢复线程的运行也需要时间。调用sleep()方法并不会让线程释放它所持有的同步锁;而且在这期间它也不会阻碍其它线程的运行。上面的连个方法都声明抛出一个InterruptedException类型的异常,这是因为线程在sleep()期间,有可能被持有它的引用的其它线程调用它的interrupt()方法而中断。中断一个线程会导致一个InterruptedException异常的产生,如果你的程序不捕获这个异常,线程就会异常终止,进入终止状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块(可能还有finally语句块)以及以后的代码。

Thread t = new Thread(){


@Override
public void run() {
try {
System.out.print("11");
sleep(3000);
System.out.print("22");
}catch(InterruptedException e) {
System.out.print("33");
}
}

};
t.start();
t.interrupt();

这里  如果没有t.interrupt()执行 就打印出1122,如果有执行,就为1133。

join:当前线程停止执行,知道join的这个线程执行完成为止,如果它所加入的线程没有存活,则当前线程无需停止,jion(5000)让当前线程等待5s,超时

停止等待,变为可运行

wait:让线程等待(这里要注意与sleep的区别:不改变对象的机锁,即在synchronized中调用sleep,其他线程不能使用,而wait可以)

interrupt:一般不会中断正在执行的线程,只会对wait、join、sleep方法阻塞的线程中断

synchronized:同步锁,应避免在同步中使用sleep和yield方法,这样cpu资源就无法释放,其他进程就不能执行。每个对象都有一个锁与之对应,它是作用

在对象在堆中的地址上,所有在栈上内容就无法加锁,如对象的引用、基本类型。

notify、notifyAll、wait:这三个是基于Object类,所有 所有对象都有这三个方法。

这里说下notify和notifyAll:

我们在synchronized同步锁的时候,如果有一个线程来执行,就会获取这个锁的一个通行证,如果在它还未执行完归还通行证的时候,有其他线程来执行,那

最新来的那些线程就会形成一个等待队列,称为schedule,当我们拥有通行证的那个线程执行完毕归还通行证,通过拥有通行证的这个对象notify,会唤醒一个线程,

具体是哪个线程由jvm来决定,notifyAll就是唤醒所有线程。

学习了上面的内容,我们可以通过下面几个题目来练习下:

1.有三个线程ID分别是A、B、C,请有多线编程实现,在屏幕上循环打印10次ABCABC

public class ThreadDemo {
	
	/**
	 * 这里是利用同步对象来实现三个线程循环打印ABC
	 */
	
	/**
	 * 先定义一个单例对象锁
	 */
	static class DemoLock {
		private static DemoLock mDemoLock = null;
		private char charactor = 'A';
		
		
		public static DemoLock getInstance() {
			if (mDemoLock == null) {
				mDemoLock = new DemoLock();
			}
			return mDemoLock;
		}
		

		public void setCharactor() {
			this.charactor += 1;
			if (this.charactor == 'D') {
				this.charactor = 'A';
			}
		}
		
		public char getCharactor() {
			return this.charactor;
		}
		
	}
	
	
	static class DemoRunnable implements Runnable {
		private DemoLock mDemoLock;
		private char mChar = ' ';
		
		public DemoRunnable(DemoLock lock, char charactor) {
			this.mDemoLock = lock;
			this.mChar = charactor;
		}
		
		@Override
		public void run() {
			//定义一个循环遍历
			int i = 0;
			while(i < 10) {
				synchronized(mDemoLock) {
					//这里我们第一个的mDemoLock.getCharactor肯定是A,然后如果不是A线程,那就wait
					//直到A线程执行完后继续,setCharactor完后是B,只有等B线程循环完后才继续,一直循环
					while(this.mChar != mDemoLock.getCharactor()) {
						try {
							mDemoLock.wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					//打印出这个值
					System.out.println(this.mChar);
					i++;
					mDemoLock.setCharactor();
					mDemoLock.notifyAll();
				}
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		DemoLock mLock = DemoLock.getInstance();
		
		Thread mThreadA = new Thread(new DemoRunnable(mLock, 'A'));
		Thread mThreadB = new Thread(new DemoRunnable(mLock, 'B'));
		Thread mThreadC = new Thread(new DemoRunnable(mLock, 'C'));
		mThreadA.start();
		mThreadB.start();
		mThreadC.start();
	}

}

public class ThreadDemo1 {
	public static void main(String[] args) {
		Thread_E tc = new Thread_E();
		Thread_E tb = new Thread_E();
		Thread_A ta = new Thread_A();
		
		ta.setThread(tb);
		tb.setThread(tc);
		tc.setThread(ta);

		
		ta.setName("A");
		tb.setName("B");
		tc.setName("C");

		tb.start();
		tc.start();
		ta.start();
		
	}
}
/**这里我们简单介绍下实现方法:
 * Thread_A先打印当前线程的名字吗,然后通过this.join等待直到被中断唤醒,并对中断t线程
 * Thread_E先通过this.join等待直到被中断唤醒,然后打印当前线程名称并中断t线程
 * 这样我们通过mian里面的代码可以看到:如果A线程先执行,那就打印出A线程名称,则等待,然后中断B线程
 * ,B线程执行,则等待,直到A线程执行完中断B线程,它会被唤醒,打印B线程名称并中断C线程
 * C线程执行,则等待,直到B线程执行完中断C线程,它会被唤醒,打印B线程名称并中断A线程
 * 这样就形成了一个循环
 */
class Thread_A extends Thread {
	Thread t;
	public void setThread(Thread t) {
		this.t = t;
	}
	public void run() {
		int i = 0;
		while(i++ < 10) {
			System.out.print(Thread.currentThread().getName());
			t.interrupt();
			try {
				//这里会一直等待,直到当前线程被中断才会继续执行
				this.join();
			} catch (InterruptedException e) {
				
			}		
		}
	}
}
class Thread_E extends Thread {
	Thread t;
	public void setThread(Thread t) {
		this.t = t;
	}
	public void run() {
		int i = 0;
		while(i++ < 10) {
			try {
				//这里会一直等待,直到当前线程被中断才会继续执行
				this.join();
				
			} catch (InterruptedException e) {
				
			}		
			System.out.print(Thread.currentThread().getName());
			t.interrupt();
		}
	}
}

2.多线程实现1+...100

3.生产值和消费者实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值