一、控制线程
控制线程即join线程提供让一个线程等待另一个线程完成的方法:join()方法。
某线程调用其它线程的join()方法时,主动调用线程将被阻塞,知道被调用线程执行完为止。
代码示例:
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 Exception{
//启动子线程
new JoinThread("新线程").start();
for(int i = 0;i < 100;i++){
if(i == 20){
JoinThread jt = new JoinThread("被Join的线程");
jt.start();
//main线程调用了jt线程的join方法,main线程必须等 jt 线程执行结束
//才会向下执行
jt.join();
}
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
上段代码中有三个线程,主线程,在主方法开始时启动了名字为"新线程"的子线程,该子线程
和main'线程并发执行。当i = 20 时,启动名为"被join的线程"的线程,该线程不会和main线程
并发执行,而是main线程必须在等待该线程执行结束之后才会向下执行,"被join的线程"与"新
线程"并发执行,而主线程处于等待状态。
二、后台线程
在后台运行,为其它线程提供服务,被称为后台线程(Daemon Thread)。
如果所有的前台线程都死亡,后台线程自动死亡。
调用Thread对象的setDaemon()方法可将指定的线程设置成后台线程。
代码示例:
public class DaemonThread extends Thread{
//定义后台线程的线程执行体与普通线程没有区别
public void run(){
for(int i = 0;i < 100;i++){
System.out.println(getName() + " " + i);
}
}
public static void main (String [ ] args){
DaemonThread t = new DaemonThread();
//将此线程设置成后台线程
t.setDaemon(true);
//启动后台线程
t.start();
for(int i = 0;i < 10;i++){
System.out.println(Thread.currentThread().getName() + " " + i);
}
//程序执行到此处,前台线程(main线程)结束,后天线程也随之结束。
}
}
Thread类还提供一个isDaemon()方法,用于判断指定的线程是否为后台线程。
三、线程睡眠:sleep
Thread类的静态sleep方法可以让正在执行的线程暂停一段时间,进入阻塞状态。
sleep方法有两种重载形式:
1、static void sleep(long millis):让当前正在执行的线程暂停milllis毫秒,并进入阻塞状态
2、static void sleep(long millis,int nanos):让当前正在执行的线程暂停millis毫秒加nanos
毫微妙,并进入阻塞状态。(其中第二种方法较少用)
代码示例:
public class TestSleep{
public static void main(String [ ] args) throws Exception{
for(int i =0;i<10;i++){
System.out.println("当前时间:" + new Data());
//调用sleep方法让当前线程暂停1s
Thread.sleep(1000);
}
}
}
四、线程让步:yield
yield() 方法和sleep()类似也不同,是Thread类的一个静态方法,作用是让当前正在执行的
线程暂停,但是不会阻塞当前线程,只将该线程转入就绪状态。这样处理器会重新从就绪
队列中调度一个优先级最高的进程投入运行。
代码示例:
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) throws Exception{
// 启动两条并发线程
TestYield ty1 = new TestYield("线程一");
ty1.start();
TestYield ty2 = new TestYield("线程二");
ty2.start();
}
}
五、线程的优先级
每个线程的优先级与创建它的父线程的优先级相同。
Thread类提供了setPriority(int newPriority)和getPriority()方法来设置和返回指定
线程的优先级,其中setPriority方法的参数可以是一个整数,范围在1~10之间,
也可以是Thread类的三个静态常量:
MAX_PRIORITY:其值为10
MIN_PRIORITY:其值为1
NORM_PRIORITY:其值为5
代码示例:
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){
//改变主线程的优先级
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);
}
}
}
}