zoukankan      html  css  js  c++  java
  • java中的线程

    1、进程与线程的概念

      进程就是正在执行的程序,进程有自己独立的一块内存空间,一个进程中有一个或多个线程;线程是进程中的一个执行路径;以人的眼光看线程时,感觉是同时执行,但是实际上是cpu轮换执行。只是速度切换比较快,人感觉不到。举个例子,正在运行的360就是一个进程,如果同时开启电脑体检、木马查杀、电脑清理等就会出现多个执行任务,每个任务对应一个线程,感觉是同时在执行,其实是cpu轮换。属于同一进程的线程会共享同一个进程的资源:堆内存、方法区内存。好处:高效,方便。缺点:线程安全问题。

      进程是操作系统进行调度和分配资源的基本单位,进程之间相互独立。

      线程是CPU进行调度处理的最基本单位。

    2、创建线程方式

      2.1 继承Thread类,重写run(),创建对象,最后调用start()。

    class T1 extends Thread{
        public void run(){
            //任务代码
        }
    }
    
    public static void main(String[] args){
       T1 t1 = new T1();
       t1.start();  
    }

      2.2实现Runnable接口

    class MyThread implements Runnable{
        public void run(){
            任务代码
        }
    }
    
    public static void main(){
      Thread t1 = new Thread(new MyThread());
      t1.start();
    }

    2.3 实现Callable接口

    public class CallableDemon {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            FutureTask<String> futureTask = new FutureTask(() -> {
                System.out.println("lambda 表达式.....");
                return "test2";
            });
            Thread thread = new Thread(futureTask);
            thread.start();
            System.out.println("返回值是:" + futureTask.get());
        }
    }

    借助FutureTask构造器传入Callable实现类。

    注意:(1)Callable是函数式接口

       (2)call()方法,任务写在这

       (3)如何获取返回值?

    2.4 线程池

    public class MyThreadPoolDemon {
        public static void main(String[] args) {
            //创建固定数量的线程池
            //ExecutorService threadPool = Executors.newFixedThreadPool(5);
            //创建有一个线程的线程池
            //ExecutorService threadPool = Executors.newSingleThreadExecutor();
            //可扩展的线程池,不会用因为最大值太大
            ExecutorService threadPool = Executors.newCachedThreadPool();
            for (int i = 0; i < 10; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName()+"办理业务");
                });
            }
        }
    }

    运行机制:https://www.jianshu.com/p/a900d4d101b7

    3、线程的状态图

      

    4、sleep()与wait()的区别?

      (1)sleep是Thread类的静态方法,wait是Object类的方法。

      (2)sleep是持锁的,当到达指定时间后,变为就绪态,一旦得到cpu就变为运行态;而wait是不持锁的,并且需要notify或者notifyAll()唤醒。

    5、线程通讯

    /*
    * 厨师,往工作台上放菜,当工作台放不了啦,就停止做菜并通知服务员取菜,
    * 工作台最多放10个菜,
    * 服务员从工作台取菜,当没有菜时就等待并通知厨师做菜。
    */
    public class TestCommunicate1 {
        public static void main(String[] args) {
             WorkBench w = new WorkBench();
             
             Cook cook = new Cook(w);
             Waiter waiter = new Waiter(w);
             cook.start();
             waiter.start();
             
        }
    }
    class Cook extends Thread{
        private WorkBench w;
        
        public Cook(WorkBench w) {
             this.w = w;
        }
        @Override
        public void run() {
             while (true) {
                 w.put();
             }
        }
        
    }
    class Waiter extends Thread{
        private WorkBench w;
        
        public Waiter(WorkBench w) {
             this.w = w;
        }
        
        @Override
        public void run() {
             while(true){
                 w.take();
             }
        }
    }
    class WorkBench{
        private int num;//记录菜的数量
        public static final int MAX_NUM = 10;//工作台最多放10个菜
        
        //放菜方法(需要线程安全)
        public synchronized void put(){
             //当工作台放满10个菜,本线程需要等待,并通知服务员来取菜
             while(num >= MAX_NUM) {
                 try {
                     this.wait();
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }
             num++;
             try {
                 Thread.sleep(300);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             System.out.println("厨师放了一道菜,工作台还有"+num+"个菜");
             this.notify();
        }
        //取菜方法
        public synchronized void take(){
             
             while (num <= 0) {
                 try {
                     this.wait();
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
             }
             num--;
             try {
                 Thread.sleep(300);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             System.out.println("服务员端走一盘菜,工作台还有"+num+"个菜");
             this.notify();
        }
    }

      

  • 相关阅读:
    nsmutableset
    数组建立 不可变数组 排序 遍历
    字符串截取 拼接 转换 长度 查询 比较
    字典排序
    数字字典结合
    可变字典
    字典
    可变字符串
    oc block排序
    oc中文首字母排序
  • 原文地址:https://www.cnblogs.com/xingrui/p/10331892.html
Copyright © 2011-2022 走看看