Java并发编程二线程常用方法

10 篇文章 1 订阅

在上一章Java并发编程一我们对Java内存模型和线程有所了解,接下来继续学习线程的方法。

start方法

上一章讲解了三种创建线程的方法(继承Thread,实现Runnable或Callable接口),
调用start方法才是真正启动线程,调用run方法只是调用当前线程的普通方法。

sleep方法

Thread中静态方法sleep(),当一个线程调用sleep方法时,会暂时让出当前CPU的执行权,等到时间到时,会重新获取执行权,不会释放锁。代码比较简单就不多解释了。
sleep方法

interrupt方法

通过我们都会主动停止线程,而线程中stop,resume已经被摒弃了,通过interrupt我们可以完成中断线程,抛出InterruptedException异常。

public class InterruptThread extends Thread{
    InterruptThread(){
        this.start();
    }
    @Override
    public void run() {
        try {
            System.out.println("Interrupted begin");
            sleep(5000);
            System.out.println("Interrupted end");
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("Interrupted");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        InterruptThread thread = new InterruptThread();
        // 是否被中断
        System.out.println(thread.isInterrupted());
        Thread.sleep(1000);
        // 中断线程
        thread.interrupt();
    }
}

运行结果:
在这里插入图片描述

join方法

我们肯定会遇见这样一个场景,就是需要等待几件事情完成再往下执行,比如多线程计算每个月的账单,等计算完毕后再进行汇总处理。Thread中join方法可以完成这样的操作。
Join方法

运行结果:
join 开始
one join
two join
join 结束

yield方法

Thread中静态方法,正常情况下线程使用完时间片后等待下一次分配,而线程执行yield方法是自己占有CPU时间片不想用了,然后处于就绪状态,线程调度器会从线程就绪队列中获取一个优先级最高的,当然也有可能会执行刚才放弃CPU的线程。Java中是通过setPriority()设置优先级,但是没什么效果。

public class YieldThread implements Runnable {
	YieldThread(){
		new Thread(this).start();
	}
	@Override
	public void run() {
		 for (int i = 0; i < 5; i++) {
			if(i==0) {
				System.out.println(Thread.currentThread().getName()+":yield 让出cpu");
				//Thread.yield();
				//Thread.sleep(500);
			}
		}
		 System.out.println(Thread.currentThread().getName()+":yield over");
	}
	public static void main(String[] args) {
         new YieldThread();
         new YieldThread();
         new YieldThread();
         new YieldThread();
	}	
}

开启四个线程,每个线程循环五次,当i==0时执行yield方法,注释掉yield方法,执行结果:在这里插入图片描述
解开Thread.yield()再次执行:
yield方法
通过两次结果可以看出,当线程执行到yield时,会让出CPU执行权,等待下次执行,调用Sleep方法也是可以实现上面效果。
两者不同:sleep方法会将线程转为阻塞状态,等待时间到时再执行,让线程级别低的可能被执行,yield方法会将线程转为就绪状态,让线程级别高优先执行或者自身执行。

wait和notify

当线程调用一个共享变量的wait方法时,该线程就会挂起,并且让出同步锁,让其他线程可以获得锁,直到其他线程调用这个变量的notify或者notifyAll方法唤醒或者其他线程调用了该线程的interrupt()方法,该线程抛出InterruptExcetion异常返回。需要注意的是,如果调用wait方法没有获取对象的监视器锁,则会抛出IllegalMonitorStateException异常。这两个必须配合synchronized一起使用,接下来通过一个生产者消费者来说明wait和notify。
首先是定义了一个list用于存储生产的数据,定义一个变量来声明最多可添加多少:
在这里插入图片描述
然后是生产者:生产者
开启五个线程,判断list是否已满, 这里判断为什么是while而不是if是因为如果此时满了消费者消费了一个,此时唤醒生产者生产,如果使用if唤醒是从wait往下继续执行,在执行list.add(random),有可能其他生产线程就已经添加完,再添加就超过容器范围。如果使用while会再次判断是否已满,防止超出。百分之九九的情况下wati和while一起使用。list不满,则随机生产100以内的数字添加,然后使用notifyAll通知所有消费者消费数据。notify和notifyAll区别就是唤醒一个和唤醒所有wati的线程。
最后消费者:
消费者
开启10个线程去消费,如果list为空,则阻塞等待,不为空则消费数据,唤醒阻塞中的生产者继续生产。
由于机试中遇见到,还是比较经典的题,当时不会写只知道概念,还有Lock、BlockingQueue写法。

用户线程和守护线程

用户线程:前台线程,我们运行的main方法和三种方法创建的线程都是用户线程,jvm会等到用户线程使用完后才结束。
守护线程:后台线程,比如GC线程,通过设置线程的setDaemon方法(必须设置在start之前),默认为false,如果当前只有守护线程,那么jvm直接结束。

public class DaemonThread extends  Thread{
@Override
public void run() {
    while (true){
        System.out.println("守护线程");
    }
}
public static void main(String[] args) {
    DaemonThread thread = new DaemonThread();
    // 设置守护线程
    //thread.setDaemon(true);
    thread.start();
}}

当线程开启时,如果解开注释,jvm就会退出,如果不解开,那么jvm就会等用户线程运行完再退出。。
以上就是线程的几种常用方法,当然还有一些延迟方法,比如wait(Long time)等等一些,基本用法一样。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值