JAVA基础知识之多线程——控制线程

join线程

在某个线程中调用其他线程的join()方法,就会使当前线程进入阻塞状态,直到被join线程执行完为止。join方法类似于wait, 通常会在主线程中调用别的线程的join方法,这样可以保证在所有的子线程执行结束之后在主线程中完成一些统一的步骤。
下面是一个例子,

package threads;

public class JoinThread extends Thread {
	public JoinThread(String name) {
		super(name);
	}

	public void run() {
		for(int i=0; i<20; i++) {
			System.out.println(getName()+" "+i);
		}
	}

	public static void main(String[] args) throws InterruptedException {
		new JoinThread("new Thread-1").start();
		for (int i=0; i<50; i++) {
			if(i==20){
				JoinThread jt = new JoinThread("new thread-2");
				jt.start();
				//main线程调用了jt线程的join方法,main线程
				//必须等jt执行完之后才能继续执行
				jt.join();
			}
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
	}

}

执行结果,可见当主线程中i=20时,主线程被阻塞了,测试thread-1和thread-2正在执行,一直到thread-2执行结束之后,主线程才继续执行

main 0
new Thread-1 0
main 1
new Thread-1 1
main 2
new Thread-1 2
main 3
new Thread-1 3
main 4
new Thread-1 4
main 5
new Thread-1 5
main 6
new Thread-1 6
main 7
new Thread-1 7
main 8
new Thread-1 8
main 9
new Thread-1 9
main 10
new Thread-1 10
main 11
new Thread-1 11
main 12
new Thread-1 12
main 13
new Thread-1 13
main 14
new Thread-1 14
main 15
new Thread-1 15
main 16
new Thread-1 16
main 17
new Thread-1 17
main 18
new Thread-1 18
main 19
new Thread-1 19
new thread-2 0
new thread-2 1
new thread-2 2
new thread-2 3
new thread-2 4
new thread-2 5
new thread-2 6
new thread-2 7
new thread-2 8
new thread-2 9
new thread-2 10
new thread-2 11
new thread-2 12
new thread-2 13
new thread-2 14
new thread-2 15
new thread-2 16
new thread-2 17
new thread-2 18
new thread-2 19
main 20
main 21
main 22
main 23
main 24
main 25
main 26
main 27
main 28
main 29
main 30
main 31
main 32
main 33
main 34
main 35
main 36
main 37
main 38
main 39
main 40
main 41
main 42
main 43
main 44
main 45
main 46
main 47
main 48
main 49

后台线程:setDaemon

后台线程有个特征就是,如果所有前台线程都死亡,后台线程会自动死亡。JVM的垃圾回收器就是一种典型的后台线程。Thread提供了一个isDaemon方法判断是否为后台线程。

下面是一个例子,注意必须在线程start之前设置(setDaemon(true))为后台线程。

package threads;

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) {
		DaemonThread t = new DaemonThread();
		//必须在start之前设置成后台线程
		t.setDaemon(true);
		t.start();
		for (int i=0; i<3; i++) {
			System.out.println(Thread.currentThread().getName()+" "+i);
		}
		//main进程运行到此处时结束,后台进程也会随之结束
	}
}

执行结果,可以看到子线程的i并没有累加到1000就结束了,因为子线程被设置成了后台线程,主线程先于子线程结束,子线程也就随之结束了

main 0
Thread-5 0
main 1
Thread-5 1
main 2
Thread-5 2
Thread-5 3
Thread-5 4
...
Thread-5 199
Thread-5 200
Thread-5 201
Thread-5 202

线程睡眠:sleep

sleep数Thread类的一个静态方法,让当前线程进入阻塞状态。

在sleep指定的时间到达之前,线程都不会获得执行机会,即使有可用的CPU执行片,因此sleep方法常常用来暂停线程。

sleep方法需要抛出一个异常。

下面是一个例子,

package threads;

import java.util.Date;

public class SleepThread {
	public static void main(String[] args) throws InterruptedException {
		for (int i=0; i<10; i++) {
			System.out.println("time:" + new Date());
			Thread.sleep(1000);
		}
	}
}

执行结果,

time:Wed Nov 16 12:00:58 CST 2016
time:Wed Nov 16 12:00:59 CST 2016
time:Wed Nov 16 12:01:00 CST 2016
time:Wed Nov 16 12:01:01 CST 2016
time:Wed Nov 16 12:01:02 CST 2016
time:Wed Nov 16 12:01:03 CST 2016
time:Wed Nov 16 12:01:04 CST 2016
time:Wed Nov 16 12:01:05 CST 2016
time:Wed Nov 16 12:01:06 CST 2016
time:Wed Nov 16 12:01:07 CST 2016

线程优先级 及 线程让步:yield

优先级

JAVA 使用setPriority改变线程优先级。JVM提供了三个常量可在不同平台使用,分别是MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY,当然也可以使用1。。10之类的数字,但是不同平台定义的数字不同,所以还是推荐用常量。

yield

yield也是Thread类的一个静态方法,它和sleep有些类似,都可以暂停当前线程,不同的是它不会让线程进入阻塞状态,而是直接进入就绪状态,让当前线程重新进入资源竞争中,此时只有优先级等于或者高于当前线程的其他线程才能获取CPU资源执行,否则被yield的线程将重新获取资源继续执行。

下面是一个例子,

package threads;

public class YieldThread extends Thread{
	public YieldThread(String name) {
		super(name);
	}

	public void run() {
		for ( int i = 0; i<50; i++) {
			System.out.println(getName()+" "+i);
			if (i == 20) {
				Thread.yield();
			}
		}
	}

	public static void main(String[] args) throws InterruptedException {
		YieldThread yt1 = new YieldThread("thread-1");
		yt1.setPriority(Thread.MAX_PRIORITY);
		//yt1.setPriority(7);
		yt1.start();
		Thread.sleep(1);

		YieldThread yt2 = new YieldThread("thead-2  ");
		yt2.setPriority(Thread.MIN_PRIORITY);
		//yt2.setPriority(1);

		yt2.start();
	}
}

执行结果,可以看到,因为thread-1优先级比thread-2高,所以无轮是thread-1调用了yield还是thread-2调用了yield,都是thread-1先抢到资源继续执行

thread-1 0
thread-1 1
thread-1 2
thread-1 3
thread-1 4
thread-1 5
thread-1 6
thread-1 7
thread-1 8
thread-1 9
thread-1 10
thread-1 11
thread-1 12
thread-1 13
thread-1 14
thread-1 15
thread-1 16
thread-1 17
thread-1 18
thread-1 19
thread-1 20
thread-1 21
thread-1 22
thread-1 23
thead-2   0
thread-1 24
thead-2   1
thread-1 25
thead-2   2
thread-1 26
thead-2   3
thread-1 27
thead-2   4
thread-1 28
thead-2   5
thread-1 29
thead-2   6
thread-1 30
thead-2   7
thread-1 31
thead-2   8
thread-1 32
thead-2   9
thread-1 33
thead-2   10
thread-1 34
thead-2   11
thread-1 35
thead-2   12
thread-1 36
thead-2   13
thread-1 37
thead-2   14
thread-1 38
thead-2   15
thread-1 39
thead-2   16
thread-1 40
thead-2   17
thread-1 41
thead-2   18
thread-1 42
thead-2   19
thread-1 43
thead-2   20
thread-1 44
thead-2   21
thead-2   22
thread-1 45
thead-2   23
thread-1 46
thead-2   24
thead-2   25
thread-1 47
thead-2   26
thread-1 48
thead-2   27
thread-1 49
thead-2   28
thead-2   29
thead-2   30
thead-2   31
thead-2   32
thead-2   33
thead-2   34
thead-2   35
thead-2   36
thead-2   37
thead-2   38
thead-2   39
thead-2   40
thead-2   41
thead-2   42
thead-2   43
thead-2   44
thead-2   45
thead-2   46
thead-2   47
thead-2   48
thead-2   49

  

  

时间: 2024-10-08 06:41:03

JAVA基础知识之多线程——控制线程的相关文章

黑马程序员——Java基础知识之多线程协同

多线程协同 线程间的通讯:对资源的操作动作不同,比如说两个卡车一个拉煤一个装煤,但是他们共享了一个资源. 怎么样把这个资源拿出来?怎样把车装满?这个资源当然是一个类,他里面的组成元素就是对象!!现在我们就要有操作对象的思想了,用对象把这车装满,现在一车装一个对象. 等待唤醒机制: 用的不是sleep是wait.flag标记,这是两人沟通的方式.其实每个标记就要做一次等待或者notify,判断wait,改值notify.线程池.notify唤醒里面的线程,按顺序唤醒.wait和notify必须用在

java基础知识总结--多线程

1.扩展Java.lang.Thread类 1.1.进程和线程的区别: 进程:每个进程都有自己独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1~n个线程. 线程:同一类线程共享代码和数据空间,每一个线程有独立的运行栈和程序计数器,线程切换开销比较小. 进程和线程一样都分为五个阶段:创建.就绪.运行.阻塞.终止. 多进程是指操作系统能同时运行多个任务(程序). 多线程是指在同一个程序中有多个顺序流在执行. 1.2.在Java中要想实现多线程,有两种方法:继承Threa

Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)

线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public class Thread implements Runnable { /* What will be run. */ private Runnable target; ...... /** * Causes this thread to begin execution; the Java Virtu

Java基础知识之多线程(1)

1.认识线程 a) 对于线程来说,容易混淆的还有进程,我们用一个例子来区分它们,每次打开一个word文档,这就是一个进程,一个word中的拼写检查这是一个线程,再如每登陆一个QQ,这是一个进程,QQ中的每一个会话都是一个线程. b)对于只有一个CPU的电脑来说,一个时间点只有一个进程占用CPU 2.Java中如何实现线程 Java中实现多线程可以采用:继承Thread类,或,实现Runnable接口 a)继承Thread类,这个方式必须覆写run()方法 class 类名称 extends Th

Java基础知识之多线程(2)

线程的休眠 使用方法:public static void sleep(long millis)throws InterruptedException{} 可见该方法有异常抛出,所以要进行异常的处理. public class A implements Runnable { private String name; public A(String name) { super(); this.name = name; } @Override public void run() { // TODO

java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

 *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时候才能消费,仓空则等待. *3.当消费者发现仓储没有产品可消费的时候,会唤醒等待生产者生产. *4.生产者在生产出可以消费的产品的时候,应该通知等待的消费者去消费. 下面先介绍个简单的生产者消费者例子:本例只适用于两个线程,一个线程生产,一个线程负责消费. 生产一个资源,就得消费一个资源. 代码如下: pub

java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)

1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以可以被任意对象调用的方法,定义在Object基类中. wait()方法:对此对象调用wait方法导致本线程放弃对象锁,让线程处于冻结状态,进入等待线程的线程池当中.wait是指已经进入同步锁的线程,让自己暂时让出同步锁,以便使其他正在等待此锁的线程可以进入同步锁并运行,只有其它线程调用notify方

java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证.创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数封装的代码操作tickets,同步代码块中的锁我们可以指定.假设我们事先不知道同步函数用的是什么锁:如果在同步代码块中指定的某个锁(测试)和同步函数用的锁相同,就不会出现线程安全问题,如果锁不相同,就会发生线程安全问题. 看下面的代码:t1线程用的同步锁是obj,t2线程在操作同步函数的资源,假设不

java基础知识回顾之java Thread类学习(五)--java多线程安全问题(锁)同步的前提

这里举个例子讲解,同步synchronized在什么地方加,以及同步的前提: * 1.必须要有两个以上的线程,才需要同步. * 2.必须是多个线程使用同一个锁. * 3.必须保证同步中只能有一个线程在运行,锁加在哪一块代码 那么我们要思考的地方有:1.知道我们写的哪些是多线程代码 2.明确共享数据 3.明确多线程运行的代码中哪些语句是操作共享数据的.. 4.要确保使用同一个锁. 下面的代码:需求:两个存户分别往银行存钱,每次村100块,分三次存完. class bank{ private int