Java Thread问题汇总

如果是非线程安全,多个线程对统一个对象中的实例变量进行并发的访问时发生。产生的后果就是出现脏读。

非线程安全问题存在与实例变量中。如果是方法内部的私有变量,则不存在非线程安全问题。因为方法内部的变量是私有的。

线程的start和run方法的区别?
public static void main(String[] args) {
   
    Thread t = new Thread(){
   
        @Override
        public void run() {
   
            attack();
        }
    };
    t.run();
    t.start();
}

public static void attack() {
   
    System.out.println("Go");
    System.out.println("currentThread: " + Thread.currentThread().getName());
}
// Go
// currentThread: main
// Go
// currentThread: Thread-0

在这里插入图片描述

public synchronized void start() {
   

    if (threadStatus != 0)
        throw new IllegalThreadStateException();
    group.add(this);
    boolean started = false;
    try {
   
        // 调用本地方法,用JVM_StartThread创建一个子线程(Thread_entry)由子线程调用run方法
        start0();
        started = true;
    } finally {
   
        try {
   
            if (!started) {
   
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
   
            /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
        }
    }
}
  • 调用start()方法,会创建一个新的子线程并启动
  • run()方法只是Thread的一个普通方法的调用

Thread方法

方法名 含义
currentThread() 返回代码段正在别那个线程调用
isAlive() 判断线程是否处于活动状态。活动状态就是线程已经启动还没终止的。线程处于正在运行或者准备开始运行的状态,就认为是活动状态。
sleep() 在指定的毫秒数让当前线程休眠
getId() 取得线程的唯一标识
yield() 放弃当前CPU的资源,将他让给其他任务去占用CPU的执行时间。但放弃的时间是不确定的。有可能刚刚放弃,马上又获得CPU时间片,不会影响锁的行为
setPriority() 设置线程的优先级别
setDaemon() 设置称为守护线程
join() 使所属线程thread对象正常执行完run方法中的任务,而使当前线程无限阻塞,等待thread线程销毁之后在继续执行线程z后面的代码。

线程的优先级是具有继承性的,比如A线程启动B线程,则B线程的优先级与A是一样的。

join内部使用的wait方法进行等待。而sychronized关键字使用的是,对象监视器。原理做为同步的。

如果join过程中,当前线程对象对象被中断,则当前线程出现异常。

Join 与 Sleep的区别

方法 区别
join(Long) join(long)内部是使用wait(long)实现的,所以join(long)方法具有释放锁的特点。
Sleep(long) 该方法不会释放锁。
Sleep和Wait的区别?
  • wait是Object类中的方法,Sleep是Thread类中的方法
  • sleep()方法可以在任何地方使用
  • wait()方法只能在synchronized方法或者在synchronized块中使用(因为wait只有获得锁之后才会释放)

最主要的区别:

  • Thread.sleep()只会让出CPU,不会导致锁行为的改变。
  • Object.wait()不仅让出CPU,还会释放已经占有的同步资源锁。
notify和notifyAll的区别?

锁池:假设线程A已经拥有了某个对象(不是类)的锁,而其他线程B、C想要调用这个对象的某个synchroized方法(或者块),由于B、C线程在进入对象的synchronized方法(或者块)之前必须先获得该对象锁的拥有权,而恰巧该对象的锁目前正被线程A所占用,此时B、C线程就会被阻塞、进入一个地方去等待锁的释放,这个地方便是对象的锁池。

  • notify会从锁池中随机选择一个唤醒
  • notifyAll会唤醒锁池中所有的线程

wait与notify

wait和notify都是object中的方法

方法 方法名
wait() wait方法用来将当前线程放入阻塞队列中,并且在wait所在的代码行停止执行,直到接到通知或者被中断为之,在调用wait方法之前,线程必须获得该对象的对象级别的锁,即只能在同步方法,或者同步代码块中调用wait方法,在调用wait方法之后,当前线程释放锁。在wait返回之前,线程和其他线程竞争重新获得锁。如果调用wait时没有持有适当的锁,则抛出illegalMonitorStateException
notify() 也要在同步方法或者同步方法块中调用,线程必须获得该对象的锁,如果调用notify方法的对象没有持有适当的锁,则会抛出异常。该方法用来通知那些可能等待该对象锁的其他线程,如果有多个线程等待,则有线程规划器随机挑选一个程先wait的线程,对其发出通知notify,并使它等待获取该对象的对象锁。在执行notify之后,当前线程不会马上释放对象锁,程先wait的线程也不能马上获取该对象锁。要等到执行notify方法的线程将程序执行完成之后,当前线程才会释放锁。而程先wait状态的线程才可以获得该对象锁。
wait(long) :

​ 带一个参数的wait(long)方法的功能是等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。

简单的总结就是:

​ wait使当前线程处于等待状态,notify使等待的线程继续运行。

​ 每个锁对象都有两个队列,一个是就绪队列一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程。

​ 一个线程被唤醒后,才会进入就绪队列,等待CPU的调度,反之,一个线程被wait后,就会进入阻塞队列,等待下一次的唤醒。

​ 当线程程wait状态的时候,调用线程对象的Interrupt方法会出现InterruptExcepthion异常。

​ 方法notify只能随机唤醒一个线程。

​ 当多次调用notify方法时,会随机将等待的线程进行唤醒

总结:
  • 在执行同步代码块就会释放对象的锁。
  • 在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放。
  • 在执行同步代码块的过程中,执行了锁所属对象的wait方法,这个线程就会释放对象锁。而此线程对象就会进入线程等待池中,等待被唤醒。
Thread和Runnable的区别?
  • Thread是实现了Runnable接口的类,使得run支持多线程
  • 因类的单一继承原则,推荐使用Runnable接口
如何给run方法传递参数?
如何处理线程返回值?
  • 主线程等待

    public class CycleWait implements Runnable {
         
        private String value;
    
        public static void main(String[] args) throws InterruptedException {
         
            CycleWait cw = new CycleWait();
            Thread t = new Thread(cw);
            t.start();
            while (cw.value == null) {
         
                Thread.sleep(100);
            }
            System.out.println(cw.value)</
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值