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();
        }
    }

      

  • 相关阅读:
    我的WCF之旅(1):创建一个简单的WCF程序
    网页设计中颜色的搭配
    CSS HACK:全面兼容IE6/IE7/IE8/FF的CSS HACK
    UVa 1326 Jurassic Remains
    UVa 10340 All in All
    UVa 673 Parentheses Balance
    UVa 442 Matrix Chain Multiplication
    UVa 10970 Big Chocolate
    UVa 679 Dropping Balls
    UVa 133 The Dole Queue
  • 原文地址:https://www.cnblogs.com/xingrui/p/10331892.html
Copyright © 2011-2022 走看看