多线程

2019-12-24  本文已影响0人  dwwl

进程是资源分配的最小单位,线程是CPU调度的最小单位

每运行一个java程序,会产生一个进程,进程包含至少一个线程,每个进程对应一个JVM实例,多个线程共享JVM的堆,每个线程拥有自己的栈

Java采用单线程编程模型,程序会自动创建主线程。

当一个java程序启动的时候,创建的jvm实例中除了main线程即主线程外,还会创建其他的线程,比如GC线程

如何处理线程的返回值

三种实现方式:

第一种弊端:需要自己实现逻辑,而且不精准(指线程结束后不能立即获得返回值)

第二种弊端:做到比第一种更精准的控制,但是力度不够细

通过FutureTask获取

MyCallable.class

public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread.sleep(5000);
        return "some message";
    }
}

main()

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
        new Thread(futureTask).start();
        System.out.println(futureTask.get());
    }

当MyCallable没执行完时,futureTask的get()会阻塞直到MyCallable执行完毕

通过线程池获取

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<String> future = executorService.submit(new MyCallable());

        try {
            System.out.println(future.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown();
        }
    }

使用线程池好处:

可以提交多个Callable的实现类去让线程池并发的处理结果,方便对这些Callable的类统一管理(这只是视频所说,具体还需要学习线程池方面再说)

线程的状态

Thread的内部类

public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

sleep和wait的区别

最主要的区别:

notify和notifyAll的区别

当我们锁住的是this实例时,实际上可以用synchronized修饰这个方法。下面两种写法是等价的:

public void add(int n) {
    synchronized(this) { // 锁住this
        count += n;
    } // 解锁
}
public synchronized void add(int n) { // 锁住this
    count += n;
} // 解锁

yield

​ 当调用Thread.yield()函数时,会给线程调度器一个当前线程愿意让出CPU使用的暗示,但是线程调度器可能会忽略这个暗示,yield对锁的行为不会有影响

中断线程

目前使用的方法:

调用interrupt(),通知线程应该中断了,和yield类似,都是给个暗示

因此调用interrupt()并不能真正的中断线程,需要被调用的线程配合中断

img
上一篇 下一篇

猜你喜欢

热点阅读