Java 多线程(中)
控制线程之join
join方法:调用join方法的线程对象强制运行,该线程强制运行期间,其他线程无法运行,必须等到该线程结束后其他线程才可以运行,有人也把这种方式成为联合线程。
代码如下:
public class JoinDemo { public static void main(String[] args) throws Exception { Thread join = new Thread(new Join(),"Join线程"); join.start(); int i = 0; while(i < 500){ if(i == 100){ join.join(); } System.out.println("Main -- > " + i ++); } } } class Join implements Runnable { public void run() { int i = 0; while(i< 200){ System.out.println(Thread.currentThread().getName() + "--" + i ++ ); } } }
控制线程之Daemon
后台线程:处于后台运行,任务是为其他线程提供服务。也称为“守护线程”或“精灵线程”。JVM的垃圾回收就是典型的后台线程。
特点:若所有的前台线程都死亡,后台线程自动死亡。
设置后台线程:Thread对象setDaemon(true);
setDaemon(true)必须在start()调用前,否则出现IllegalThreadStateException异常;
前台线程创建的线程默认是前台线程;判断是否是后台线程:使用Thread对象的isDaemon()方法;
并且当且仅当创建线程是后台线程时,新线程才是后台线程。
代码如下:
class Daemon extends Thread { public void run() { for (int i = 0; i < 10000; i++) { System.out.println(getName() + "-" + i); } } } public class DaemonDemo { public static void main(String[] args) { Daemon d = new Daemon(); d.setDaemon(true);//把 d 线程设置成后台线程 d.start(); for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+"--" + i); } } }
控制线程之sleep
线程休眠:
让执行的线程暂停一段时间,进入阻塞状态,注意此方法会抛出异常。
sleep(long milllis) throws InterruptedException:毫秒
调用sleep()后,在指定时间段之内,该线程不会获得执行的机会。
代码如下:
public class SleepDemo { public static void main(String[] args) { for (int i = 10; i > 0; i--) { System.out.println("还剩" + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
控制线程之优先级
每个线程都有优先级,优先级的高低只和线程获得执行机会的次数多少有关。并非线程优先级越高的就一定先执行,哪个线程的先运行取决于CPU的调度; 默认情况下main线程具有普通的优先级,而它创建的线程也具有普通优先级。
Thread对象的setPriority(int x)和getPriority()来设置和获得优先级。
MAX_PRIORITY : 值是10
MIN_PRIORITY : 值是1
NORM_PRIORITY : 值是5(主方法默认优先级)
代码如下:
class Priority extends Thread{ public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName()+",优先级=" + getPriority() +"--"+ i); } } } public class PriorityDemo { public static void main(String[] args) { Thread.currentThread().setPriority(7); for (int i = 0; i < 100; i++) { if(i == 10){ Priority p1 = new Priority(); p1.setPriority(Thread.MAX_PRIORITY); p1.start(); } if(i == 15){ Priority p2 = new Priority(); p2.setPriority(Thread.MIN_PRIORITY); p2.start(); } System.out.println("main" + i); } } }
控制线程之yield
线程礼让:
暂停当前正在执行的线程对象,并执行其他线程;
Thread的静态方法,可以是当前线程暂停,但是不会阻塞该线程,而是进入就绪状态。所以完全有可能:某个线程调用了yield()之后,线程调度器又把他调度出来重新执行。
代码如下:
class Yield implements Runnable { public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + "--> " + i); if (i % 2 == 0) { Thread.yield();// 礼让 } } } } public class YieldDemo { public static void main(String[] args) { Yield y = new Yield(); new Thread(y, "A").start(); new Thread(y, "C").start(); } }
控制线程之结束线程
boolean flag = true;//用变量来控制线程 public void run() { int i = 0; while (flag) { if (i == 25) { flag = false; } System.out.println("==" + i); i++; } }
API过时方法--易死锁,不推荐使用
stop:终止线程
马上让线程停止运行,并释放该线程所持有的锁,该操作无法保证对象的内部状态正确;
suspend:挂起线程
使线程进入“阻塞”状态,该状态下CPU不会分给线程时间片,进入这个状态可以用来暂停一个线程的运行,在被resume方法调用前,不可用.
如果要suspend的目标线程对一个重要的系统资源持有锁,那么没任何线程可以使用这个资源直到要suspend的目标线程被resumed。
resume:恢复线程
恢复被suspend方法挂起的线程