java线程(二)——常用方法

一.join()

join方法的作用是,执行该方法的线程进入阻塞状态,直到调用该方法的线程结束后再由阻塞转为就绪状态。

在如下代码中:

第9、10行:创建TimeThread线程对象,并开启该线程。

第11、12行:在主线程中使用for循环执行五次,打印五行简单数据。

第13行:当for循环执行到第三次的时候用timeThread线程对象调用join对象,此时由于该行代码是主线程执行的,所以此时主线程会进入阻塞状态,又因为该join方法是由timeThread线程调用的,所以此时在运行中的线程就只有timeThread了,且只有等timeThread线程运行结束之后主线程才可以从阻塞状态变为就绪状态。

第29行:为了使运行结果更容易分析,所以在timeThread线程中打印的内容设置的较为复杂一点,这样在调用join方法之前timeThread线程就不会抢在主线程之前执行了。

注意,调用join方法的线程类对象必须是已经start过的对象,否则调用join并不会使其进入运行状态。

package thr;

import java.util.Date;

public class Test {

	public static void main(String[] args) {
		TimeThread timeThread = new TimeThread();
		timeThread.start();
		for(int i=0;i<5;i++) {
			System.out.println("主线程:"+i);
			if(i==2) {
				try {
					timeThread.join();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

class TimeThread extends Thread{

	@Override
	public void run() {
		for(int i=0;i<5;i++) {
			System.out.println("计数2:"+new Date());
		}
	}
}

以下是运行结果,可以看到在打印“主线程:2”之后便开始打印“计数2”直至五次打印完才回来继续打印“主线程”:

二.interrupt()

该方法用于结束线程在调用Object类的wait方法或该类的join方法、sleep方法过程中的阻塞状态,并在调用wait、join和sleep方法处产生InterruptedException异常,下面用sleep方法的阻塞来举例:

第6、7行:创建TimeThread线程的对象,并开启该线程。

第9到13行:在八秒阻塞后主线程打印111111

第15行:timeThread对象调用interrupt中断TimeThread线程的阻塞。

第24行:设置调用sleep方法对该线程进行阻塞。

package thr;

public class Test {

	public static void main(String[] args) {
		TimeThread timeThread = new TimeThread();
		timeThread.start();
		try {
			Thread.sleep(8000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(111111);
		
		timeThread.interrupt();
	}
}

class TimeThread extends Thread{

	@Override
	public void run() {
		try {
			sleep(10000000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		for(int i=0;i<5;i++) {
			System.out.println("计数2:"+i);
		}
	}
}

下面是运行结果,中断阻塞后会报InterruptedException异常,然后继续执行完TimeThread线程。

三.currentThread()

该方法返回当前正在执行的线程对象,用法为:Thread thread = Thread.currentThread()

但是该方法的使用上要注意,谁执行该行代码,thread就代表谁。

以下示例中,由于该行代码在主线程中执行,所以代表的是主线程的对象。

package thr;

public class Test {

	public static void main(String[] args) {
		Thread thread = Thread.currentThread();
		System.out.println(thread);
	}
}

运行结果如下,打印的是主线程对象的信息,第一个main是线程的名字,第二个值是线程的优先级,第三个main是指所属的线程组。

而如果该行代码在TimeThread线程中执行,则thread代表的即是TimeThread线程对象,如下示例:

package thr;

public class Test {

	public static void main(String[] args) {
		TimeThread timeThread = new TimeThread();
		timeThread.start();
	}
}

class TimeThread extends Thread{

	@Override
	public void run() {
		Thread thread = Thread.currentThread();
		System.out.println(thread);
	}
}

四.isAlive()

该方法用于判定该线程是否处于就绪、运行或阻塞状态,或者说线程是否存活,如果是则返回true,否则返回false。

使用示例如下:

该段代码在TimeThread线程中定义了一个传入主线程对象的构造方法,这样就可以在TimeThread线程中监控主线程了。

执行到第8行时:timeThread线程开启,执行run方法。

执行到第23行:timeThread线程阻塞一秒,阻塞的这一秒中主线程继续接过运行权。

执行到第9行:由于thread对象的创建语句是在主线程中执行的,所以thread代表的是主线程对象,所以该语句作用是判断主线程此刻是否存活,因为该判断语句就是主线程中执行的,所以主线程自然处于存活状态,一定会打印true。

执行到第27行:此时主线程执行完毕,timeThread线程的阻塞也结束,该语句中的thread在构造方法中已经被赋值为主线程中的thread对象,即是主线程对象,所以调用isAlive方法的对象还是主线程对象,此处还是在监控主线程的存活状态,由于刚才在timeThread线程阻塞的一秒内足以运行完主线程,所以主线程自然是死亡状态,此处一定会打印false。

package thr;

public class Test {

	public static void main(String[] args) {
		Thread thread = Thread.currentThread();
		TimeThread timeThread = new TimeThread(thread);
		timeThread.start();
		System.out.println("##########"+thread.isAlive());
	}
}

class TimeThread extends Thread{

	Thread thread;
	public TimeThread(Thread thread) {
		this.thread=thread;
	}
	
	@Override
	public void run() {
		try {
			sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("$$$$$$$$$$"+thread.isAlive());
	}
}

五.setDaemon(boolean on)

在线程对象调用start之前调用setDaemon且值设置为true,则该线程为守护线程。

守护线程的特点就是随着进程中最后一个非守护线程的结束而结束,也就是说即使守护线程没有执行完,但是进程中已没有非守护线程了,这时守护线程会自动结束。

以下是示例:

当第7行代码被注释掉的时候,TimeThread为非守护线程,此时该线程中为一个死循环,无论主线程是否结束它都会一直输出,所以得到的运行结果如下:

package thr;

public class Test {

	public static void main(String[] args) {
		TimeThread timeThread = new TimeThread();
		//timeThread.setDaemon(true);
		timeThread.start();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

class TimeThread extends Thread{
	
	@Override
	public void run() {
		for(int i=0;;i++) {
			System.out.println(i);
		}
	}
}

而如果把第7行的代码解注释,将TimeThread设置为守护线程,这时主线程在阻塞五秒后结束时TimeThread线程也会跟着一起结束,得到运行结果如下:

六.setPriority(int newPriority)

设置当前线程的优先级,Java线程的优先级用整数表示,取值范围是1~10,当执行同一个线程类创建的线程对象的前提下,线程优先级越高,线程获得执行的次数越多。

但是如果两个线程不是同一个类,则优先级就不存在可比性了,因为毕竟不同的线程内语句的复杂度不相同,所以该方法在实际中使用的并不多。

发布了99 篇原创文章 · 获赞 93 · 访问量 5240

猜你喜欢

转载自blog.csdn.net/DangerousMc/article/details/100043543