多线程相关问题(一)

由于近期在做知识储备,在做很多的复习,把之前看过的内容重温一遍真的像重新看一遍一样,真的是一入JAVA深似海。

概念相关问题

1.线程和进程有什么区别?

线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。

2.线程的状态有哪些?

Java线程状态转换.jpg

相关方法问题

1.start和run方法的区别?

在这里我们先写一段代码来实际感受一下这两个方法的区别。

/**
 * 针对run()和 start()区别的测试类
 */
public class ThreadTest {

    /**
     * 单纯打印执行内容以及当前线程的线程名
     */
    private static void doTest(String name) {
        System.out.println("使用"+ name + "方法调用doTest()");
        System.out.println("Current Thread is : " + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        Thread startThread = new Thread() {
            @Override
            public void run() {
                doTest("start()");
            }
        };

        Thread runThread = new Thread() {
            @Override
            public void run() {
                doTest("start()");
            }
        };
        startThread.start();

        runThread.run();
    }

}

执行结果


结果.png
具体分析

我们先来看一下java.lang.Thread#start方法的源码

public synchronized void start() {
    /**
     * This method is not invoked for the main method thread or "system"
     * group threads created/set up by the VM. Any new functionality added
     * to this method in the future may have to also be added to the VM.
     *
     * A zero status value corresponds to state "NEW".
     */
    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    /* Notify the group that this thread is about to be started
     * so that it can be added to the group's list of threads
     * and the group's unstarted count can be decremented. */
    group.add(this);

    boolean started = false;
    try {
        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 */
        }
    }
}

上述源码中 实际启动的就是 start0();这个方法。我们查看源码可以看到 这个方法也是一个native方法。

private native void start0();

我们接着查看一下native中的相关源码。这里就直接给出源码以及重点,具体怎么查询的可以自行百度。

start.png
start1.png

由上述的虚拟机源码,我们可以就可以看明白刚刚我们写的demo中的结果的原因了。

总结

图解:

总结.png
  • 调用start()时,会创建一个新的子进程并启动
  • 调用run()时,支持thread的普通方法调用,依旧在主线程中调用。

2.sleep()和wait()的区别?

  • sleep()是Thread类的方法,wait()是Object类中定义的方法。
  • sleep()方法可以在任何地方使用,wait()只能在synchronized方法或代码快中使用
  • Thread.sleep 只会让出cpu,不会导致锁行为的改变
  • Object.wait不仅让出cpu,还会释放已经占有的同步锁资源

3.notify() 和 notifyAll()的区别?

首先需要了解一下两个概念。

锁池
锁池.png
等待池
等待池.png
  • notifyAll()让所有处于等待池的线程全部进入锁池去竞争锁的机会
  • notify() 会随机选择一个线程进入锁池去竞争。

4.yield和join的区别?

  • 一个调用yield()方法的线程告诉虚拟机它乐意让其他线程占用自己的位置。这表明该线程没有在做一些紧急的事情。注意,这仅是一个暗示,并不能保证不会产生任何影响。
  • 得一个线程在另一个线程结束后再执行。如果join()方法在一个线程实例上调用,当前运行着的线程将阻塞直到这个线程实例完成了执行。

5.调用Interrupt()函数

  • 如果线程处于被阻塞状态,那么线程将立即退出被阻塞状态,并抛出一个InterruptedException异常。
  • 如果线程处于正常活动状态,那么会将该线程的中断标志设置为true,被设置中断标志的线程将继续正常运行。不受影响。
  • 需要被调用的线程配合中断
    • 在正在运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程。

你可能感兴趣的:(多线程相关问题(一))