线程基础

1 线程状态 1.1.2

  1. New:尚未启动的线程,创建了没启动;
  2. Runnable:可运行线程的状态,等待CPU调度;
  3. Blocked:线程阻塞等待监视器锁定的状态;处于synchronized同步代码块或方法中被阻塞。
  4. Waiting:等待线程的线程状态。下列不带超时的方式:Object.wait/Thread.join/LockSupport.park
  5. Timed Waiting:具有指定等待时间的等待线程的线程状态。下列带超时的方式:Thread.sleep/Object.wait/Thread.join/LockSupport.parkNanos/LockSupport.parkUntil
  6. Terminated:终止线程的线程状态。

2 线程状态的跳转

3 线程的终止 1.1.3

   3.1 不合理的终止

      首先需要终止的线程是这样的:

public class StopThread extends Thread {
  private int i = 0, j = 0;

  @Override
  public void run() {
    synchronized (this) {
	    // 增加同步锁,确保线程安全
	    ++i;
	    try {
	      // 休眠10秒,模拟耗时操作
	      Thread.sleep(10000);
	    } catch (InterruptedException e) {
	      e.printStackTrace();
	    }
	    ++j;
    }
  }

  /** * 打印i和j */
  public void print() {
  System.out.println("i=" + i + " j=" + j);
  }
}

不合理的终止,就是用线程的stop方法进行终止,其实这个方法已经被废弃了。

  public static void main(String[] args) throws InterruptedException {
    StopThread thread = new StopThread();
    thread.start();
    // 休眠1秒,确保i变量自增成功
    Thread.sleep(1000);
    // 暂停线程
   //  thread.stop(); // 错误的终止
   thread.interrupt(); // 正确终止
    while (thread.isAlive()) {
      // 确保线程已经终止
    } // 输出结果
    thread.print();
  }

 用stop方法的结果打印是i=1,j=0;用interrupt方法的结果打印是i=1,j=1;

小结:如果线程调用了wait,sleep,join等,被阻塞了,那么interrupt方法会生效,线程的中断状态会被清除。

4 线程之间的通信 1.1.5

   要实现多个线程之间的协同,如:线程的先后执行控制,获取某个线程执行的结果等等。涉及线程之间的相互通信,分为下面四类: 1、文件共享;2、网络共享;3、变量共享;4、JDK提供的线程协调API。前面这3点很好理解,就是多个线程,大家一起去操作一个公共的东西。第四点主要有wait/notify和park/unpark,suspend/resume已经被弃用了。

    4.1 Wait/Notify

这些方法只能由同一个对象锁的持有者线程调用,也就是写在同步代码块中,否则会抛出异常。wait方法会导致当前线程等待,加入到该对象的等待集合中,并且放弃当前持有的对象锁。notify/notifyall方法唤醒一个或者多个正在等待这个对象锁的线程。注意wait虽然会自动释放锁,但是有顺序要求,如果在notify之后才开始wait,那么就会出问题。

4.2 park/unpark

     park和unpark是不会释放锁的,如果在同步代码块中加了park/unpark,先后顺序出了问题,就会导致死锁。

4.3 伪唤醒

线程可能会被某种异常伪唤醒,如果用if判断某个条件是否发生,那么线程就走下去了,所以最好改成用while循环判断,这样就不会被伪唤醒影响。

		new Thread(() -> {
				synchronized (this) {
					while (baozidian == null) { // 如果没包子,则进入等待
					try {
						System.out.println("1、进入等待");
						this.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
			System.out.println("2、买到包子,回家");
		}).start();

5 线程封闭 1.1.6

多线程访问共享可变数据时,涉及到线程间数据的同步问题,并不是所有时候都需要用到共享数据,所以就提出了线程封闭的概念。数据都被封闭在各自的线程之中,就不需要同步了。线程封闭的具体体现有ThreadLocal和局部变量。这里主要说说ThreadLocal。

public class Demo6_my {
    public static  ThreadLocal<String> value=new ThreadLocal<>();

    public static void main(String[] args) {
        value.set("123 from main");
        new Thread(()->{

            System.out.println("value= "+value.get());
            value.set("456 from"+Thread.currentThread().getName());
            System.out.println("value= "+value.get());
        }).start();

        System.out.println("In main: "+value.get());
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值