Java控制活动切换_Java-线程的一些控制方法

一、Java 中的线程状态转换

f25b34d97004

【注】不是 start 之后就立刻开始执行,只是就绪了(CPU 可能正在运行其他的线程)。只有被 CPU 调度之后,线程才开始执行,当 CPU 分配给的时间片到了,又回到就绪状态,继续排队等候。

二、线程控制的基本方法

isAlive():判断线程是否还活着。start 之后,终止之前都是活的。

getPriority():获得线程的优先级数值。

setPriority():设置线程的优先级数值(线程是有优先级别的)。

Thread.sleep():将当前线程睡眠指定毫秒数。

join():调用某线程的该方法,将当前线程与该线程合并,也即等待该线程结束后,再恢复当前线程的运行状态(比如在线程B中调用了线程 A 的 join(),直到线程A执行完毕后,才会继续执行线程B)。

yield():当前线程让出 CPU,进入就绪状态,等待 CPU 的再次调度。

wait():当前线程进入对象的 wait pool。

notify()/notifyAll():唤醒对象的 wait pool 中的一个/所有的等待线程。

三、isAlive():判定线程是否处于活动状态

//判定线程是否处于活动状态 : --就绪状态 --运行状态 --阻塞状态

public class Demo2 {

public static void main(String[] args) {

new ThreadB().start();

}

}

class ThreadB extends Thread {

@Override

public void run() {

System.out.println("检测线程是否是活动状态");

System.out.println(Thread.currentThread().isAlive());

}

}

四、setPriority():设置线程的优先级

//设置线程优先级 MAX_PRIORITY:最大为10

// MIN_PRIORITY:最小为1

// DEFAULT_PRIORITY:默认为5

public class Demo4 {

public static void main(String[] args) {

ThreadD td = new ThreadD();

ThreadE te = new ThreadE();

td.start();// 谁先启动,谁抢占资源的概率越大

te.start();

td.setPriority(Thread.MAX_PRIORITY);// 设置优先级为最大,10

te.setPriority(Thread.MIN_PRIORITY);// 设置优先级为最小,1

}

}

class ThreadD extends Thread {

@Override

public void run() {

// 默认优先级为5

// System.out.println(Thread.currentThread().getPriority());

for (int i = 0; i < 10; i++) {

System.out.println("ThreadD j---" + i);

}

}

}

class ThreadE extends Thread {

@Override

public void run() {

for (int i = 0; i < 10; i++) {

System.out.println("ThreadE i---" + i);

}

}

}

ThreadD j---0

ThreadE i---0

ThreadE i---1

ThreadE i---2

ThreadE i---3

ThreadE i---4

ThreadE i---5

ThreadE i---6

ThreadE i---7

ThreadE i---8

ThreadE i---9

ThreadD j---1

ThreadD j---2

ThreadD j---3

ThreadD j---4

ThreadD j---5

ThreadD j---6

ThreadD j---7

ThreadD j---8

ThreadD j---9

五、sleep():将当前线程睡眠指定毫秒数

可以调用 Thread 的静态方法:

public static void sleep(long millis) throws InterruptedException在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响,该线程不丢失任何监视器的所属权。InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态被清除。

由于是静态方法,sleep() 可以由类名直接调用:Thread.sleep(.....);

class TestThread {

public static void main(String[] args) {

MyThread thread = new MyThread();

thread.start();

try { // 在哪个线程中调用 Sleep,就让哪个线程睡眠

Thread.sleep(8000); // 主线程睡8秒后,打断子线程

} catch (InterruptedException e) {

}

thread.interrupt(); // 打断子线程

}

}

class MyThread extends Thread {

@Override

public void run() {

while(true){

System.out.println("=== "+ new Date()+" ===");

try {

sleep(1000); // 每隔一秒打印一次日期

} catch (InterruptedException e) {

return;

}

}

}

}

=== Tue May 09 11:09:43 CST 2017 ===

=== Tue May 09 11:09:44 CST 2017 ===

=== Tue May 09 11:09:45 CST 2017 ===

=== Tue May 09 11:09:46 CST 2017 ===

=== Tue May 09 11:09:47 CST 2017 ===

=== Tue May 09 11:09:48 CST 2017 ===

=== Tue May 09 11:09:49 CST 2017 ===

=== Tue May 09 11:09:50 CST 2017 ===

子线程每隔一秒打印系统日期,主线程睡眠8秒后,打断子线程,子线程结束。

在本例中,采用一种简单、粗暴、好用的方法中断子线程:

class TestThread {

public static void main(String[] args) {

MyThread thread = new MyThread();

thread.start();

try { // 在哪个线程中调用 Sleep,就让哪个线程睡眠

Thread.sleep(5000); // 主线程睡8秒后,打断子线程

} catch (InterruptedException e) {

}

thread.flag = false; // 打断子线程

}

}

class MyThread extends Thread {

boolean flag = true;

@Override

public void run() {

while(flag){

System.out.println("=== "+ new Date()+" ===");

try {

sleep(1000); // 每隔一秒打印一次日期

} catch (InterruptedException e) {

}

}

}

}

=== Tue May 09 12:21:24 CST 2017 ===

=== Tue May 09 12:21:25 CST 2017 ===

=== Tue May 09 12:21:26 CST 2017 ===

=== Tue May 09 12:21:27 CST 2017 ===

=== Tue May 09 12:21:28 CST 2017 ===

六、join():合并某个线程,相当于方法的调用

class TestThread {

public static void main(String[] args) {

MyThread myThread = new MyThread("childThread");

myThread.start();

try {

myThread.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

for(int i = 1; i <= 4; i++){

System.out.println("I am the mainThread");

}

}

}

class MyThread extends Thread {

public MyThread(String name) {

super(name);

}

@Override

public void run() {

for(int i = 1; i <= 4; i++){

System.out.println("I am " + getName());

try {

sleep(1000);

} catch (InterruptedException e) {

return;

}

}

}

}

I am childThread

I am childThread

I am childThread

I am childThread

I am the mainThread

I am the mainThread

I am the mainThread

I am the mainThread

在A中调用B的join()函数,等B的函数执行完毕,在执行A的函数。

七、yield():让出 CPU,当前线程进入就绪状态队列等待,给其他线程执行的机会(就让很小的一个时间片段)。

class TestThread {

public static void main(String[] args) {

MyThread my1 = new MyThread("t1");

MyThread my2 = new MyThread("t2");

my1.start();

my2.start();

}

}

class MyThread extends Thread {

public MyThread(String s) {

super(s);

}

@Override

public void run() {

for(int i = 1; i <= 100; i++){

System.out.println(getName()+":"+i);

if(i % 10 == 0) {

Thread.yield(); // 当前线程让出 CPU 一小会儿

}

}

}

}

八、wait():它会释放掉对象的锁

当前的线程必须拥有当前对象的 monitor,也即 lock,就是锁。线程调用 wait(),释放它对锁的拥有权,使得当前线程必须要等待。然后等待另外的线程调用 notify() 或者 notifyAll()来通知它,这样它才能重新获得锁的拥有权和恢复执行。要确保调用 wait() 的时候拥有锁,即:wait() 的调用必须放在 synchronized 方法或synchronized 块中。

区别:

1️.当线程调用了 wait() 时,它会释放掉对象的锁。

2️.另一个会导致线程暂停的方法:Thread.sleep(),它会导致线程睡眠指定的毫秒数,但线程在睡眠的过程中是不会释放掉对象的锁的。

九、notify()/notifyAll():唤醒对象的wait pool 中的一个/所有等待线程

notify() 会唤醒一个等待当前对象的锁的线程。如果多个线程在等待,它们中的一个将会选择被唤醒。这种选择是随意的,和具体实现有关(线程等待一个对象的锁是由于调用了 wait() 中的一个)。被唤醒的线程是不能被执行的,需要等到当前线程放弃这个对象的锁。被唤醒的线程将和其他线程以通常的方式进行竞争,来获得对象的锁。也就是说,被唤醒的线程并没有什么优先权,也没有什么劣势,对象的下一个线程还是需要通过一般性的竞争。

notify() 应该是被拥有对象的锁的线程所调用This method should only be called by a thread that is the owner of this object's monitor。换句话说,和 wait() 一样,notify() 调用必须放在 synchronized 方法或synchronized 块中。

十、一个线程变为一个对象的锁的拥有者的三种方法

执行这个对象的 synchronized 实例方法。

执行这个对象的 synchronized 语句块。这个语句块锁的是这个对象。如 synchronized (object)

对于 Class 类的对象,执行那个类的 synchronized、static 方法。

十一、守护线程,必须在它的start()之前进行设置,通过setDaemon()传入true的参数,当程序只有守护线程时,该程序就可以结束运行了。

//守护线程:在线程启动前设置setDaemon(true)

public class Demo6 {

public static void main(String[] args) throws Exception {

ThreadH th = new ThreadH();

th.setDaemon(true);// 让当前线程设置为守护线程

th.start();

for (int i = 0; i < 10; i++) {

Thread.sleep(1000);

System.out.println("主线程。。。" + i);

}

}

}

class ThreadH extends Thread {

int i;

@Override

public void run() {

while (true) {

try {

sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("Hello,---" + ++i);

}

}

}

十二、Thread 类中的 start() 和 run() 的区别

start() 来启动线程,真正实现了多线程运行。

线程类的 start() 可以用来启动线程;该方法会在内部调用 Runnable 接口的 run(),以在单独的线程中执行 run() 中指定的代码。

这时无需等待 run 方法体代码执行完毕,可以直接继续执行下面的代码。通过调用 Thread 类的 start() 来启动一个线程,这时此线程是处于就绪状态,并没有运行。

然后通过此 Thread 类调用 run() 来完成其运行操作的,这里 run() 称为线程体,它包含了要执行的这个线程的内容,run() 运行结束,此线程终止。然后CPU再调度其它线程。

start() 启动线程执行以下任务:

它统计了一个新线程

线程从 New State 移动到 Runnable 状态。

当线程有机会执行时,它的目标 run() 将运行。

run() 当作普通方法的方式调用。程序还是要顺序执行,要等待 run 方法体执行完毕后,才可继续执行下面的代码;程序中只有主线程——这一个线程,其程序执行路径还是只有一条,这样就没有达到写线程的目的。

调用 start() 才可启动线程,而 run() 只是 thread 的一个普通方法调用,还是在主线程里执行。把需要并行处理的代码放在 run() 中,start() 启动线程将自动调用 run() ,这是由JVM的内存机制规定的。并且 run() 必须是 public 访问权限,返回值类型为void。

start() 不能多次调用,否则抛出java.lang.IllegalStateException。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值