Java多线程系列之:多线程基础

一,基础概念

1,CPU核心数和线程的关系

  CPU核心数:最早的cpu是单核的。后来出现了多核cpu(2核,4核)

  CPU和线程的个数是1:1的关系。比如4核可以允许4个线程同时运行。后来intel提出了超线程的概念。使cpu和线程个数1:2。

2,CPU时间片轮转机制

  给每一个进程分配一个时间段,这个时间段就被称为进程的时间片 ---> 这个进程允许运行的时间。
  不同进程在cpu上执行,cpu需要进行不同进程之间的切换。每次切换需要耗费5000-20000个时钟周期。这其实是浪费了cpu的资源。
  我们在开发时,尽量减少让cpu去进行进程间的切换。

3,什么是线程和进程

  进程:程序运行进行资源分配的最小单位。一个进程内部有多个线程,多个会共享这个进程的资源
  线程:CPU调度的最小单位,线程不拥有资源。线程依附于进程。

4,并行和并发

  并行:某一个时间点,可以处理的事情(同一时刻,可以处理事情的能力)
  并发:与时间单位相关,某个时间段内,可以处理的事情(单位时间内可以处理事情的能力)

二,认识Java里的线程

1,Java里的程序天生就是多线程的,比如我们执行main方法时,并不是只有main这个主线程,还有别的线程在运行:

/**
 * java天生就是多线程的
 */
public class OnlyMain {
    public static void main(String[] args) {
        
        //Java虚拟机线程管理的接口。
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        
        //通过这个类可以拿到当前应用程序有多少个线程
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false,false);
        
        for (ThreadInfo threadInfo:threadInfos){
            System.out.println("["+threadInfo.getThreadId()+"] "+threadInfo.getThreadName());
        }
        /**
         * 打印结果:说明执行main方法时至少启动了5个线程
         [5] Monitor Ctrl-Break
         [4] Signal Dispatcher
         [3] Finalizer
         [2] Reference Handler
         [1] main                      main方法线程
         */
    }
}

2,启动新线程的三种方式:

/**
 * 创建线程的三种方式
 */
public class NewThread {

    /**
        方式一:扩展自Thread类
    */
    private static class UseThread extends Thread{
        @Override
        public void run() {
            System.out.println("i am extends Thread");
        }
    }

    /**
        方式二:实现Runnable
     */
    private static class UseRun implements Runnable{
        @Override
        public void run() {
            System.out.println("i am implements Runnable");
        }
    }

    /*
        方式三:实现Callable接口,允许有返回值
     */

    private static class UseCall implements Callable<String>{
        @Override
        public String call() throws Exception {
            System.out.println("i am implements Callable");
            return "CallResult";
        }
    }

    public static void main(String[] args) throws InterruptedException,ExecutionException{

        //Thread启动线程
        UseThread useThread = new UseThread();
        useThread.start();

        //Runnable启动线程
        UseRun useRun = new UseRun();
        new Thread(useRun).start();

        //Callable启动线程
        UseCall useCall = new UseCall();
        /**
         * 注意:
         * 1,Callable是不能直接交给Thread的
         * 2,可以把Callable包装成Runnable。FutureTask实现了Runnable接口
         * 3,包装成Runnable后,交给Thread
         */
        FutureTask<String> futureTask = new FutureTask<String>(useCall);
        new Thread(futureTask).start();
        //我们可以从Callable拿到返回值。注意:get()方法是阻塞的
        String result = futureTask.get();
        System.out.println(result);
    }
}

3,Java提供了Thread类,为什么还要提供Runnable接口?

从面向对象的角度思考:Java是单继承的,提供Runnable接口可以多实现。

 

猜你喜欢

转载自www.cnblogs.com/inspred/p/11096591.html