java 线程(二)线程常用方法

上一篇讲解了线程与线程池创建的一些方法,这期讲线程常用方法与线程池之间的区别。

上一篇中实现线程有继承Thread与实现Runnable接口两种。这里建议用Runnable,因为接口可以实现多继承,且只有一个run方法。

start方法与run方法:

start方法来启动线程,真正的实现了多线程,因为这是无需等待run()方法体里的代码是否执行完毕,它会继续执行下面的代码。当启动了start方法,就启动了一个线程,线程处于就绪状态,直到得到cpu时间片,就会执行run方法。当run方法体运行结束,这个线程也就结束。

run方法只是一个普通的方法,run方法体里面写了要执行的内容,直接调用run方法,程序中也只是有主线程一个线程,仍需等待run方法里面的方法体执行完毕后,才能继续执行下面的代码。这样就是去了并发的意义。

总结:start方法会开辟一条新线程,并且只能被调用一次(因为一个线程只能被初始化一次),当调用start时,线程会进入就绪阶段,当初始化完毕jvm会自动调用run方法来执行run方法里面的方法体。而run方法是由jvm直接调用的,他只是一个普通方法。如果我们没用启动线程(调用start),直接调用run方法,这样并不会开辟新的线程,而是运行在当前的线程中(即run方法所在的线程中),这样就违背了创建线程的初衷。


用户线程和守护线程的区别
二者其实基本上是一样的。唯一的区别在于JVM何时离开。

用户线程:当存在任何一个用户线程未离开,JVM是不会离开的。

守护线程:如果只剩下守护线程未离开,JVM是可以离开的。
 

常用方法:

 getId():获取线程的id
getName():获取线程的名字
t.getPriority():获取线程优先级
t.isAlive():判断是否处于活跃状态
t.isDaemon()):是否为守护线程

getState():获取线程状态

isinterrupted:判断线程是否中断

setPriority():设置线程优先级

interrupt:用于中断线程,抛出interrupted异常

jion:如果当前线程中调用线程对象join,当前线程阻塞,直到线程对象的run执行完毕,当前线程阻塞结束。

wait: 当执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放锁,使得其他线程能够被访问,可以通过notify和notifyAll方法来唤醒。

yield:暂停当前执行的线程对象,并执行其他线程。就是当前线程交出cpu权限,让cpu及执行其他线程。不释放锁

sleep:当调用sleep方法时,会暂时让出cpu的执行权,等到时间到时会重新获得执行权,不会释放锁。

yield与sleep区别:yield不能控制具体的交出时间,并且yield只能让相同优先级的线程获取被cpu执行的机会,yield不会进入阻塞状态,而是就绪状态。

synchronized:同步监视器(俗称锁)

当两个并发的线程访问同一个对象中的这个加锁同步代码块时,同一时刻最多只有一个线程能执行这段代码。

下面我们来看一个案例:

众所周知:试衣间是不能两个异性同时进的!!!我们模拟两个人不认识的人同一时间在商场购买衣服,而商场只有一个试衣间。

public class Demo10 {
    static Object o=new Object();

    public static void main(String[] args) {
      Thread t=new Thread("杨过"){
          public void run(){
              shoping(Thread.currentThread().getName());
          }
      };

            Thread t1=new Thread("容么么"){
                public void run(){
                    shoping(Thread.currentThread().getName());
                }
            };
            t.start();
            t1.start();
    }
    public  static void shoping(String name){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(name+"进入商场");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name+"开始挑衣服");
        synchronized (o) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + "进入试衣间");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + "走出试衣间");
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name+"结账走人");
    }
}

运行结果:

 我们在试衣间部分上了锁也就是说,这两个进程不能同时访问试衣间的那段代码,必须要等一个线程执行完毕后另一个线程才能执行。也就是说这两个线程并发,两个线程执行什么,执行快慢都可以,但到了加锁同步代码块时,另一个线程必须等待那段代码执行完毕,另一个线程才能访问那段代码块。

CountDownLatch与CyclicBarrier:

CountDownLatch:

CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0时,await()方法会阻塞程序继续运行。CountDownLatch能够使一个线程等待其他线程完成各自的工作后再执行。

public class Demo10 {
    public static void main(String[] args) {
        CountDownLatch cdl=new CountDownLatch(3);
        Thread t1=new Thread(){
            public  void  run(){
                System.out.println(Thread.currentThread().getName()+"开始");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"完毕");
                cdl.countDown();
            }
        };
        Thread t2=new Thread(){
            public  void  run(){
                System.out.println(Thread.currentThread().getName()+"开始");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"完毕");
                cdl.countDown();
            }
        };
        Thread t3=new Thread(){
            public  void  run(){
                System.out.println(Thread.currentThread().getName()+"开始");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"完毕");
                cdl.countDown();
            }
        };

        Thread thread=new Thread(){
            public void run(){
                try {
                    cdl.await();//等待阻塞   其他线程全部执行完毕
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("火箭发射。。。。");
            }
        };
        thread.start();
        t1.start();
        t2.start();
        t3.start();

    }
}

运行结果:

可以看到三个线程都结束后,最后的线程才执行。

CyclicBarrier:

CyclicBarrier的字面意思是可循环使用的屏障。它要做的事情是让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所以被屏障拦截的线程才会继续干活。每个线程调用await方法告诉CyclicBarrier我已经到达屏障,然后当前线程被阻塞。

public class Demo11 {
    public static void main(String[] args) {
        CyclicBarrier c=new CyclicBarrier(5);
        for (int i=0;i<11;i++){
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Thread t=new Thread(){
                public void run(){

                    System.out.println(Thread.currentThread().getName()+"来了");
                    try {
                        c.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName()+"走了");

                }
            };
            t.start();
        }
    }
}

运行结果:(太长了没截图。)

Thread-0来了
Thread-1来了
Thread-2来了
Thread-3来了
Thread-4来了
Thread-4走了
Thread-0走了
Thread-1走了
Thread-3走了
Thread-2走了
Thread-5来了
Thread-6来了
Thread-7来了
Thread-8来了
Thread-9来了
Thread-9走了
Thread-5走了
Thread-7走了
Thread-8走了
Thread-6走了
Thread-10来了


以上我们可以看到只有当线程到达5的时候才会继续执行,而当运行到Thread-10时循环到达最大次数,没有新的进程加入,所以不会继续执行了。

CountDownLatch与CyclicBarrier区别:
       CountDownLatch:一个线程或者多个线程,等待另外N个线程完成某个事情之后才能执行。只有一个等待线程,其他N个线程都可以顺利执行完毕。(可以简单理解为发射火箭,必须等待其他工作完成才能发射)

       CyclicBarrier:N个线程互相等待,任何一个线程完成之前,所有线程都必须等待。在最后一个未await之前,所有N个线程都不算完成,都处于阻塞状态。(可以简单理解为运动会百米赛跑,必须达到一定人数,裁判才会开枪)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值