线程的优先级 :
Java语言中线程有优先级,优先级高的线程会获得较多的运行机会。 当程序中有多个线程存在的时候,线程和线程之间的关系并非是平等的。
Java语言中线程的优先级用整数表示,取值范围是1~10,Thread类由以下三个静态常量表示线程的优先级。
(1)static int MAX_PRIORITY
线程可以具有的最高优先级,取值为10。
(2)static int MIN_PRIORITY
线程可以具有的最低优先级,取值为1。
(3)static int NORM_PRIORITY
分配给线程的默认优先级,取值为5。
Thread类的方法setPriority()和getPriority()分别用来设置和获取线程的优先级。
package thread;
public class _5_线程的优先级 {
public static void main(String[] args) {
MySleeps ms = new MySleeps();
Thread t1 = new Thread(ms,"a");
Thread t2 = new Thread(ms,"b");
Thread t3 = new Thread(ms,"c");
System.out.println(t1.getPriority());//默认的优先级为普通的优先级——5
t1.setPriority(Thread.MAX_PRIORITY);//最大——10
t3.setPriority(Thread.MIN_PRIORITY);//最小——1
t1.start();
t2.start();
t3.start();
}
}
class MySleeps implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0 ; i<40 ; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
由上图的运行结果可以知道,优先级高的可以获得更多的机会优先执行。
Java中虽然提供了10个线程优先级,但是这需要电脑操作系统的支持,不同操作系统对优先级的支持是不一样的,不能很好的和Java中线程优先级一一对应。
因此,在设计多线程应用程序的时候,其功能的实现一定不能依赖于线程的优先级,而只能将线程的优先级作为一种提高程序效率的手段。
线程睡眠:
方法Thread.sleep(long millis),使线程转到阻塞状态。millis参数设定睡眠的时间,以ms为单位。当睡眠结束后,就转为就绪(Runnable)状态。
当睡眠时间到期,则返回到可运行状态。
睡眠的位置:为了让其他线程有机会执行,可以将Thread.sleep()的调用放线程run()之内。这样才能保证该线程执行过程中会睡眠。
sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。
package thread;
public class _6_Sleep线程睡眠 {
public static void main(String[] args) {
MySleep ms = new MySleep();
Thread t1 = new Thread(ms,"a");
Thread t2 = new Thread(ms,"b");
Thread t3 = new Thread(ms,"c");
t1.start();
t2.start();
t3.start();
}
}
class MySleep implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0 ; i<40 ; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==6)
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
在结果中可以看出,当i==6的时候,该线程就会进入短暂的睡眠,而进行下一个线程的运行(也有可能进入睡眠后又醒了继续抢夺cpu,继续进行该线程,就是几率有点小)
线程让步:
方法Thread.yield(),暂停当前正在执行的线程对象,把执行机会让给相同或者更高优先级的线程。
package thread;
public class _7_yield线程让步 {
public static void main(String[] args) {
//创建两个线程
Thread t1 = new YieldThread("one");
Thread t2 = new YieldThread("two");
//开启两个线程
t1.start();
t2.start();
}
}
class YieldThread extends Thread{
public YieldThread(String name) {
super(name);
}
public void run() {
for(int i = 0 ; i < 5 ; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==2) {
System.out.println("线程让步");
Thread.yield();
}
}
}
}
该方法与sleep(参数)方法类似,都可以让当前正在运行的线程暂停,区别在于yield()方法不会阻塞该线程,它只是将线程转换为就绪状态,让系统的调度器重新调度一次。当某个线程调用yield()方法后,与当前线程优先级相同或者更高的线程可以获得执行的机会。
由于Java虚拟机默认采用抢占式调度模式,所有线程都会再次抢占CPU资源抢夺权,所以执行线程让步后不能保证立即执行其他线程。
线程插队(加入):
方法join(),等待这个线程执行结束。在当前线程中调用另一个线程的方法join(),则当前线程转入阻塞状态,直到另一个线程运行结束,当前线程再由阻塞转为就绪状态。
package thread;
public class _8_join线程插队 {
public static void main(String[] args) {
MyJoin mj = new MyJoin();
Thread t = new Thread(mj,"one");
t.start();
for(int i = 0 ; i <40;i++) {
System.out.println("main "+i);
if(i==20)//加入的线程先运行完再运行主线程
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class MyJoin implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0 ; i <40;i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
可以看出,当main=20的时候,进行了插队,当one线程全部结束的时候才继续进行main线程
线程类的常用方法:
- 类方法
- 实例方法