Java线程--多线程常用的几个方法

sleep()

sleep()方法属于Thread类,主要的作用是让当前线程停止执行,把cpu让给其他线程执行,但不会释放对象锁和监控的状态,到了指定时间后线程又会自动恢复运行状态

注意:线程睡眠到期自动苏醒,并返回到可运行状态,不是运行状态。sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行

  • 另外

    • Thread.sleep()方法是一个静态方法

    • Java有两种sleep方法,一个只有一个毫秒参数,另一个有毫秒和纳秒
      个参数第三代

sleep(long millis)

or

sleep(long millis, int nanos)

1//此try语句块放在run方法内
2try {
3            Thread.sleep(1000);
4       } catch (InterruptedException e) {
5            // TODO 自动生成的 catch 块
6            e.printStackTrace();
7       }

wait() notify()

wait()属于Object类,与sleep()的区别是当前线程会释放锁,进入等待此对象的等待锁定池。比方说,线程A调用Obj.wait(),线程A就会停止运行,而转为等待状态。至于等待多长时间? 那就看其他线程是否调用Obj.notify().其优势显而易见,成为多个线程之间进行通讯的有手段!

注意:它必须包含在Synchronzied语句中,无论是wait()还是notify()都需要首先获得目标的对象的一个监视器

  • 先来解释一下 "Synchronzied"
    是一种同步锁。作用是实现线程间同步,对同步的代码加锁,使得每一次,只能有一线程进入同步块,从而保证线程间的安全性

它修饰的对象有以下几种:

  • 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的部分,进入同步代码前要获得给定对象的锁

  • 修饰一个实例方法,进入同步代码前要获得当前实例的锁

  • 修饰一个静态方法,进入同步代码前要获得当前类的锁

先给大家一个例子:

 1public class SimpleWN {
 2    public static int count=0;
 3    public static class one implements Runnable{
 4        @Override
 5        public void run() {
 6            for (int i = 0; i < 100; i++) {
 7                synchronized (this) {
 8                    count++;
 9                }
10            }                           
11        }   
12    }
13    public static void main(String[] args) throws InterruptedException {
14        Thread t1=new Thread(new one());
15        Thread t2=new Thread(new one());
16        t1.start();
17        t2.start();
18        t1.join();
19        t2.join();
20        System.out.println(count);
21    }
22}

不知道大家看出这段代码有一个严重错误。代码17,18行,两个线程实例的不是同一个对象,这也意味两个线程使用的是两把不同的锁,没法保证同步。多运行几次就会发现有时候结果并不是200

更正做法:

1    one oo=new one();
2    Thread t1=new Thread(oo);
3    Thread t2=new Thread(oo);

举例说明程序中应用wait() 和 notify():

 1public class SimpleWN {
 2    final static Object object=new Object();
 3    public static class one extends Thread{
 4        @Override
 5        public void run() {
 6            synchronized (object) {
 7                System.out.println("T1 开始");
 8                try {
 9                    System.out.println("T1 等待");
10                    object.wait();
11                } catch (InterruptedException e) {
12                    e.printStackTrace();
13                }
14                System.out.println("T1 结束");
15            }                   
16        }   
17    }
18    public static class two extends Thread{
19        @Override
20        public void run() {
21            synchronized (object) {
22                System.out.println("T2 开始");
23                System.out.println("释放一个线程");
24                object.notify();
25                System.out.println("T2 结束");
26            }                   
27        }   
28    }
29    public static void main(String[] args) throws InterruptedException {
30        Thread t1=new one();
31        Thread t2=new two();
32        t1.start();
33        t2.start();
34        t1.join();
35        t2.join();
36    }
37}

运行结果:

T1 开始
T1 等待
T2 开始
释放一个线程
T2 结束
T1 结束

join()

在某些情况下,子线程需要进行大量的耗时运算,主线程可能会在子线程执行结束之前结束,但是如果主线程又需要用到子线程的结果,换句话说,就是主线程需要在子线程执行之后再结束。这就需要用到join()方法

 1public class BigJoin {
 2    public static int count;
 3    public static class AddThread implements Runnable{
 4        @Override
 5        public void run() {
 6            for (int i = 0; i < 1000000000; i++) {
 7                count++;
 8            }   
 9        }   
10    }
11    public static void main(String[] args) throws InterruptedException {
12        // TODO 自动生成的方法存根
13        AddThread addThread=new AddThread();
14        Thread t1=new Thread(addThread);
15        t1.start();
16        t1.join();
17        System.out.println(count);
18    }
19}

yield()

中文意思:放弃,屈服
一个线程调用yield()意味着告诉虚拟机自己非常乐于助人,可以把自己的位置让给其他线程(这只是暗示,并不表绝对)。但得注意,让出cpu并不代表当前线程不执行了。当前线程让出cpu后,还会进行cpu资源的争夺,但是能不能再次分配到,就不一定了。

yield()做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的 目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被 线程调度程序再次选中。

 
 1public class SimpleYield extends Thread{
 2    String name=null;
 3    public  SimpleYield(String name) {
 4        super(name);
 5    }
 6    @Override
 7    public void run() {
 8        // TODO 自动生成的方法存根
 9        for(int i=1;i<=10;i++){
10            System.out.println(this.getName()+i);
11            if(i==5){
12                this.yield();
13            }
14        }
15    }
16    public static void main(String[] args) throws InterruptedException {
17        SimpleYield t1=new SimpleYield("小花");
18        SimpleYield t2=new SimpleYield("小草");
19        t1.start();
20        t2.start();
21    }
22}

运行结果:这只是其中一种结果,线程(小花)的执行到2时把cpu让给线程(小草)并执行,接下来-线程(小草)的执行到2时把cpu让给线程(小花)并执行

1  小花1
2  小花2
3  小草1
4  小草2
5  小花3
6  小花4
7  小草3
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值