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方法挂起的线程