控制线程

原创 2013年12月05日 22:55:32


1.join线程
在某条线程执行中调用其他线程的join()方法时,调用线程将被阻塞,直到被join方法加入的join线程完成为止。
join方法有三种重载的形式:
1)join():等待被join的线程执行完成。
2)join(long millis):等待被join的线程的时间最长为millis毫秒。如果在millis毫秒内,被join的线程还没有执行结束则不再等待。
3)join(long millis, int nanos):等待被join的线程的时间最长为millis毫秒加上nanos微妙。
见下面程序:
public class JoinThread extends Thread {
	
	//提供一个有参数的构造器,用于设置该线程的名字
	public JoinThread(String name){
		super(name);
	}
	//重写run方法,定义线程执行体
	public void run() {
		for(int i = 0; i < 100; i++){
			System.out.println(getName() + " " + i);
		}
	}

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

		//启动子线程
		new JoinThread("新线程").start();
		
		for(int i = 0; i < 100; i++) {
			if(i == 20) {
				JoinThread jt = new JoinThread("被join的线程");
				jt.start();
				//主线程调用了jt线程的join方法
				//主线程必须等jt执行结束才会向下执行
				jt.join();
			}
			System.out.println(Thread.currentThread().getName() + " " +i);
		}
	}

}

运行程序


程序中一共有3条线程,主方法开始时就启动了名为“新线程”的子线程,并与其并发执行。当主线程循环变量i等于20时,启动了名为“被join的线程”,该线程不会和主线程并发执行,而是主线程必须等该线程之行结束后才可以向下执行。


2.后台线程(Deamon Thread)
后台线程,即在后台运行的线程,它的任务是为其他的线程提供服务。JVM的垃圾回收线程就是典型的后台线程。后台线程有个特征:如果所有的前台线程都死亡,后台线程会自动死亡。调用Thread对象setDaemon(true)方法可将指定线程设置成后台线程。
public class DaemonThread extends Thread {
	//定义后台线程的线程执行体与普通线程没有任何区别
	public void run() {
		for(int i = 0; i < 1000 ; i++) {
			System.out.println(getName() + "------" + i);
		}
	}

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

		DaemonThread dt = new DaemonThread();
		//将此线程设置成后台线程
		dt.setDaemon(true);
		//启动后台线程
		dt.start();
		
		for(int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName() + "------" + i);
		}
		//程序执行到此处,前台main线程结束
		//后台线程也随之结束
	}

}

运行程序

前台线程死亡后,JVM会通知后台线程死亡。但从后台接受命令到做出响应,需要一定时间。
后台线程t线程本来应该执行到i等于999时才会结束,但该后台线程无法运行到999,因为当唯一的前台线程主线程运行结束后,JVM会主动退出,因而后台线程也就被结束了。

注:要将某个线程设置为后台线程,必须在该线程启动之前设置,也就是setDaemon(true)必须在start()方法之前调用。否则会引发IllegalThreadStateException异常。


3.线程睡眠
当需要将当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用Thread类的静态sleep方法。当当前线程调用sleep方法进入阻塞状态后,在其sleep时间段内,该线程不会获得执行的机会,即使系统中没有其他可运行的线程,处于sleep中的线程也不会运行。
public class TestSleep  {

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

		for(int i = 0; i < 5 ; i++) {
			System.out.println("当前时间:" + new Date());
			//调用sleep方法让当前线程暂停1s
			Thread.sleep(1000);
		}
	}
}

运行程序

输出每条字符串之间的时间间隔是1秒。

注:sleep()和wait()的异同
相同:都进入冻结状态,放弃执行资格,CPU会去执行其他线程
不同:sleep不会放弃锁;而wait会放弃锁。


4.线程让步
yeild()方法是Thread类提供的一个静态方法。它会让当前正在执行的线程暂停,但它不会阻塞该线程,它只是将该线程转入就绪状态。yield只是让当前线程暂停一下,让系统的线程调度器重新调度一次,完全可能的情况是:当某个线程调用了yield方法暂停之后,线程调度器又将其调度出来重新执行。
实际上,当某个线程调用了yield方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的就绪状态的线程才会获得执行的机会。
public class TestYield extends Thread {
	
	public TestYield(){}
	
	public TestYield(String name){
		super(name);
	}
	//定义run方法作为线程执行体
	public void run() {
		for(int i = 0; i < 50; i++){
			System.out.println(getName() + " " + i);
			//当i等于20时,使用yield方法让当前线程让步
			if(i == 20) {
				Thread.yield();
			}
		}
	}

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

		//启动两条并发线程
		TestYield ty1 = new TestYield("高级");
		//将ty1线程设置成最高优先级
		//ty1.setPriority(Thread.MAX_PRIORITY);
		ty1.start();
		
		TestYield ty2 = new TestYield("低级");
		//将ty1线程设置成最高优先级
		//ty2.setPriority(MIN_PRIORITY);
		ty2.start();
	}

}

运行结果

当系统线程调度器重新调度时,由于两条线程的优先级完全一样,所以系统当一条线程使用yield方法暂停后,另一条线程就会开始运行。

如果将ty1.setPriority(Thread.MAX_PRIORITY);和ty1.setPriority(Thread.MIN_PRIORITY);两句代码的注释取消后,也就是为两条线程分别设置不同的优先级,程序运行结果:

低级线程执行到20调用yield后,让给高级线程执行。


5.改变线程优先级
每个线程执行时都具有一定优先级,优先级高的线程获得较多的执行机会,而优先级低的线程获得较少的执行机会。每个线程默认的优先级与创建它的父类具有相同的优先级,在默认情况下,主线程具有普通优先级,有主线程创建的子线程也有普通优先级。
Thread提供了setPriority(int newPriority)方法设置线程的优先级,参数可以是一个整数,范围是1-10之间。也可以使用Thread类的三个静态常量:
---->MAX_PRIORITY:其值是10。
---->MIN_PRIORITY:其值是5。
---->NORM_PRIORITY:其值是1。
public class PriorityTest extends Thread {
	
	public PriorityTest(){}
	//定义有参构造器,用于创建线程时指定name
	public PriorityTest(String name){
		super(name);
	}

	public void run() {
		for(int i = 0; i < 50; i++){
			System.out.println(getName() + ",其优先级是:" + getPriority() + ",循环变量是:" + i);
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//改变主线程的优先级
		Thread.currentThread().setPriority(6);
		for(int i = 0; i < 30; i++){
			if(i == 10) {
				PriorityTest low = new PriorityTest("低级");
				low.start();
				System.out.println("创建之初的优先级" + low.getPriority());
				//设置该线程为最低优先级
				low.setPriority(Thread.MIN_PRIORITY);
			}
			
			if(i == 20) {
				PriorityTest high = new PriorityTest("高级");
				high.start();
				System.out.println("创建之初的优先级" + high.getPriority());
				//设置该线程为最高优先级
				high.setPriority(Thread.MAX_PRIORITY);
			}
		}
	}

}

运行结果

可以看到优先级高的线程后的执行机会更多。


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

利用event控制线程同步.rar

  • 2007-09-03 00:26
  • 172KB
  • 下载

1.1.2获取和控制线程状态(Getting and Seeting Thread State)

1.1.2获取和控制线程状态(Getting and Seeting Thread State) 一个线程对象联合着一个线程的状态。这个状态包含着一个名字、一个表明线程是活着还是死着、执行线程的状态(...

使用Condition类控制线程通信

在开发程序中,当我们常常需要并发处理一下程序来提高运行效率,在保证线程安茜以及执行线程通信情况下,相对于传统JavaObject的线程通信来说,Condition类来控制线程通信可以为多个线程建立不同...

使用Condition控制线程通信

一.需求 实现线程间的通信,主线程循环3次后,子线程2循环2次,子线程3循环3次,然后主线程接着循环3次,如此循环3次. 即:A->B->C---A->B->C---A->B->C ...

Java多线程之控制线程

控制线程Java的线程支持,提供了便捷工具,方便控制线程的执行。包括join线程,后台线程,线程睡眠sleep,线程让步yield,改变线程优先级prioriy。join线程Thread提供了让一个线...

多线程(5)- 控制线程

停止线程,守护线程,join方法,线程的优先级,线程让步

多线程04:《疯狂Java讲义》学习笔记——控制线程

(1)join线程;(2)后台线程;(3)线程睡眠:sleep;(4)线程让步:yield;(5)改变线程优先级

Java中怎么控制线程访问资源的数量

在API中是这样来描述Semaphore 的 Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目。 一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)