多线程与并发

多线程与并发

1、进程与线程

  • 1、什么是进程
    • 程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念,而进程是程序在处理机上的一次执行过程,他是一个动态的概念。
    • 进程是一个具有独立功能的程序,一个实体,每一个进程都有他的自己的地址空间
  • 2、进程的状态
    • 进程执行的间断性,决定了进程可能具有多种状态,事实上,运行中的进程有以下的三种基本状态
      • 1、就绪状态
      • 2、运行状态
      • 3、阻塞状态
  • 3、线程
    • 线程实际上是在进程基础上的进一步划分,一个线程启动之后, 里面的若干程序又可以划分成若干个线程
    • 线程:是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少又一个线程(单线程程序)
  • 4、线程实现的两种方式
    • 在java中如果想要实现多线程的操作,可以由以下两个方式
      • (1)集成Thread类
                 public static void main(String[] args) {
            
                    //创建一个线程对象
                    MyThread t1 = new MyThread();
                    //t1.run();//直接调用不是启动线程,而是在本线程中执行方法
                    //开始执行
                    t1.start();  //线程已经准备好了  就绪状态  等待cpu的调度
                }
            
                /**
                 * 继承Thread实现线程
                 * 
                 * @author wuyinlei
                 *
                 */
                static class MyThread extends Thread {
                    @Override
                    public void run() {
                        // 在此方法中编写要执行的工作
                        for (int i = 0; i < 10; i++) {
                            System.out.println(System.currentTimeMillis() + "-" + i);
                        }
                    }
                }
 * (2)实现Runnable接口(推荐使用,面象接口编程)
                static class MyRunnable implements Runnable {
        
                @Override
                public void run() {
                    // 在此方法中编写要执行的工作
                    for (int i = 0; i < 10; i++) {
                        System.out.println(Thread.currentThread().getName() + "-" + System.currentTimeMillis() + "-" + i);
                        }
                    }
                }
                
                    //要这样调用
                    MyRunnable r = new MyRunnable();
                    Thread t2 = new Thread(r);
                    t2.start();

2、线程的操作方法

  • Thread(Runnable target) //分配新的Thread对象
  • Thread(Runnable target,String name)//分配新的Thread对象
  • Thread(String name) //分配新的对象
  • static Thread cuttentThread() //返回对当前正在执行的对象的引用
  • long getId()返回线程的标识符
  • String getName()返回线程的名称
  • void setName(String name) //改变线程的名称,使之与参数name相同
  • boolean isAlive() //测试线程是否处于活动状态
  • static void sleep(long millis) //休眠指定的毫秒数后继续执行
  • static void sleep(long millis,int nanos) //不丢失任何监视器的所有权 //休眠指定的毫秒和纳秒只有继续执行
  • void join() //等待线程终止
  • void join(long millis) //等待该线程终止的时候最长为millis的毫秒
  • void join(long millis,int nanos)
  • Thread.yield()//让出当前正在执行的线程对象,并去执行其他线程
  • boolean isDaemon()测试该线程是否为守护线程
  • void setDaemon(boolean on) //将该线程标记为守护线程或者用户线程
  • void interrupt() 终端线程
  • static boolean interrupted()测试当前线程是否已经中断
  • void setPriority(int newPrioritr) //更改线程的优先级
  • static int MAX_PRIORITY //线程可以具有的最高优先级
  • static int MIN_PRIORITY //线程可以具有的最低优先级
  • static int NORM_PRIORITY //分配给线程的默认的优先级
  • void nofify() //唤醒其他线程

3、线程同步

  • 1、多线程共享数据
    • 在多线程的操作中,多个线程有可能同时处理一个资源,这就是多线程中的共享数据
  • 2、线程同步
    • 解决线程共享问题,必须使用同步,所谓的同步就是指多个线程在同一个时间内只能有一个线程执行指定的代码,其他的线程要等待此线程执行完之后才可以继续执行
    • 线程同步的方法(两种方式)--->同步会牺牲性能,来获取安全
      • 1、同步代码块
        • synchronized(要同步的对象){ 要同步的操作;}
      • 2、同步方法
        • public synchronized void method(){要同步的操作;}
      • 3、Lock
                 // 互斥锁
                 private final ReentrantLock lock = new ReentrantLock();
            
                public void eat() {
                    lock.lock(); // 上锁
            
                    /**
                     * 这里面做出来的逻辑
                     */
            
                    lock.unlock(); // 解锁
                } 
  • 同步准则
    • 当编写synchronized块的时候,有几个简单的准则可以遵循,这些准则在避免死锁和性能危险的风险方面有很大的帮助
      • (1)是代码块保持简短,把不随线程变化的预处理和后处理溢出synchronized块。
    • (2)不要阻塞,如InputStream.read()
    • (3)在持有锁的时候,不要对其他对象调用方法

4、死锁

  • 过多的同步有可能出现死锁,死锁的操作一般是在程序运行的时候才有可能出现
  • 多线程中要进行资源的共享,就需要同步,但同步过多,就可能造成死锁
  • 中断线程(自定义中断)标志中断 让线程自己停止

5、生产者与消费者应用案例

  • 多线程的开发中又一个最经典的操作案例,就是生产者-消费者,生产者不断生产产品,消费者不断的去走产品。
  • 这里我们收下描述的是一个错乱的,我们看下运行的代码
                * /**
                 * 生产者和消费者
                 * @author wuyinlei
                 *
                 */
                public class ThreadDemo {
                
                    public static void main(String[]args){
                        Food food = new Food();
                        Producter p = new Producter(food);
                        Customer c = new Customer(food);
                        Thread t1 = new Thread(p);
                        Thread t2 = new Thread(c);
                        t1.start();
                        t2.start();
                    }
                }
                //生产者
                class Producter implements Runnable{
                    
                    private Food food;
                    public Producter (Food food){
                        this.food = food;
                    }
                    
                    @Override
                    public void run() {
                        //生产100份菜
                        for (int i = 0; i < 100; i++) {
                            if (i % 2 == 0) {
                                food.setName("东北大乱炖");
                                try {
                                    Thread.sleep(500);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                food.setEfficasy("好吃不贵真实惠");
                            } else{
                                food.setName("糖醋鲤鱼");
                                try {
                                    Thread.sleep(500);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                food.setEfficasy("酸甜口");
                            }
                        }
                    }
                }
                //消费者
                class Customer implements Runnable{
                    
                
                    private Food food;
                    public Customer (Food food){
                        this.food = food;
                    }
                    
                    
                    @Override
                    public void run() {
                        
                        for (int i = 0; i < 100; i++) {
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println(food.getName() + "--->" + food.getEfficasy());
                        }
                    }
                }
                
                //消费的对象
                class Food{
                    
                    public Food() {
                        super();
                    }
                    public Food(String name, String efficasy) {
                        super();
                        this.name = name;
                        this.efficasy = efficasy;
                    }
                    private String name; //菜名
                    private String efficasy; //功效
                    public String getName() {
                        return name;
                    }
                    public void setName(String name) {
                        this.name = name;
                    }
                    public String getEfficasy() {
                        return efficasy;
                    }
                    public void setEfficasy(String efficasy) {
                        this.efficasy = efficasy;
                    }
                }
  • 下面我们来下同步(对food的操作,那么我们就来对food进行同步)
        package com.yinlei.thread;

        import java.awt.PageAttributes;
        
        /**
         * 生产者和消费者
         * 
         * @author wuyinlei
         *
         */
        public class ThreadDemo {

                public static void main(String[] args) {
                    Food food = new Food();
                    Producter p = new Producter(food);
                    Customer c = new Customer(food);
                    Thread t1 = new Thread(p);
                    Thread t2 = new Thread(c);
                    t1.start();
                    t2.start();
                }
            }
            
            // 生产者
            class Producter implements Runnable {

        private Food food;
    
        public Producter(Food food) {
            this.food = food;
        }
    
        @Override
        public void run() {
            // 生产100份菜
            for (int i = 0; i < 100; i++) {
                if (i % 2 == 0) {
                    /*
                     * food.setName("东北大乱炖"); try { Thread.sleep(500); } catch
                     * (InterruptedException e) { e.printStackTrace(); }
                     * food.setEfficasy("好吃不贵真实惠");
                     */
                    food.set("东北大乱炖", "好吃不贵真实惠");
                } else  {
                    /*
                     * food.setName("糖醋鲤鱼"); try { Thread.sleep(500); } catch
                     * (InterruptedException e) { e.printStackTrace(); }
                     * food.setEfficasy("酸甜口");
                     */

                food.set("糖醋鲤鱼", "酸甜口");
            }
        }
            }
        }

        // 消费者
        class Customer implements Runnable {
    
        private Food food;
    
        public Customer(Food food) {
            this.food = food;
        }
    
        @Override
        public void run() {

        /*
         * for (int i = 0; i < 100; i++) { try { Thread.sleep(500); } catch
         * (InterruptedException e) { e.printStackTrace(); }
         * System.out.println(food.getName() + "--->" + food.getEfficasy());
         */
        food.get();
            }
        }

        // 消费的对象
        class Food {

        private boolean flag = true;// true表示可以生产 false表示可以消费
    
        public Food() {
            super();
        }
    
        public Food(String name, String efficasy) {
            super();
            this.name = name;
            this.efficasy = efficasy;
        }
    
        private String name; // 菜名
        private String efficasy; // 功效
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getEfficasy() {
            return efficasy;
        }
    
        public void setEfficasy(String efficasy) {
            this.efficasy = efficasy;
        }
    
        // 生产产品
        public synchronized void set(String name, String efficasy) {

        // 表示不能生产
        if (!flag) {
            try {
                this.wait(); // 当前线程进入等待状态,但是会让出cpu,并且释放锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.setName(name);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.setEfficasy(efficasy);
        flag = false; // 表示不能生产
        this.notify(); // 唤醒该监视器上的其他线程
        }
    
        // 消费产品
        public synchronized void get() {
            if (flag) {
                try {
                    this.wait(); // 当前线程进入等待状态,但是会让出cpu,并且释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.getName() + "--->" + this.getEfficasy());
            flag = true; // 表示不能再取
            this.notify(); // 唤醒该监视器上的其他线程
        }
    
          }

6、线程生命周期

7、线程池

  • 线程池是预先创建线程的一种技术,线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中,然后对这些资源进行复用,减少频繁的创建和销毁对象,
  • JDK1.5版本以上提供了线程池
  • Java里面线程池的顶级接口是Executor,是一个执行线程的工具,线程池的接口是ExecutorService
    • 在 Executors类里面提供了一些静态工厂,生成一些常用的线程池
      • newSingleThreadExecutor
        • 创建一个单线程的线程池,这个线程池只有一个线程在工作,也就是相当于单线程执行所有的任务,如果这个唯一的线程因为异常结束,那么会有一个新的线程来代替,此线程池保证所有任务的执行顺序按照任务的提交顺序
      • newFixedThreadPool:
        • 创建固定大小的线程池,每次提交一个任务就创建一个线程,直到达到线程池的最大大小
        • 线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新的线程
      • newCacheThreadPool:
        • 创建一个可缓存的线程,如果鲜橙汁的大小超过了处理任务的所需要的线程,那么就会回收部分空余时间(60s不执行任务)的线程,当任务增加时,此线程池又可以智能的添加新线程来处理任务,此线程池不会对线程池的大小做限制,线程池的大小完全依赖于操作系统(或者JVM)能够创建的最大线程大小
      • newScheduledTheradPool:
        • 创建一个大小无限制的线程池,此线程池支持定时以及周期性的执行任务的需求
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,631评论 18 399
  • 为什么要用线程池 关于为什么要使用多线程,请参考【多线程与并发】:线程的创建、状态、方法中的最后一点。 那为什么要...
    maxwellyue阅读 550评论 0 1
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,454评论 1 15
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 2,957评论 1 18
  • 这一天天把人累的喘不了气。
    卓麦阅读 141评论 1 0