2019.3.19 多线程开发相关

进程与线程

基本概念

  • 什么是进程?什么是线程?

    • 进程(Process):是OS进行资源分配和调度的基本单位。一个进程包含1到n个线程。
    • 线程(Thread):是CPU进行资源分配和调度的最小单位。线程负责处理进程中无数的小任务。
  • 进程和线程有什么特点?

    • 如果要做进程之间的数据交换和切换,开销巨大;
    • 线程的切换开销很小;
    • 线程之间共享打码和数据空间;
  • 进程创建有哪两种方式?

    • 1.继承
    • 2.接口
  • 注意事项

    • 1.在一个进程中 至少会有一个主线程;
    • 2.除了主线程之外的 都可以叫子线程;
    • 3.子线程可以有多个,如果没有限制,所有的子线程和主线程是并行的;
    • 4.线程之间如果没有资源冲突,就各自执行互不相干;

使用继承方式创建进程

新建MyThread类:


public class MyThread extends Thread {
    @Override
    public void run() {
        //在run中写要在线程中执行的代码
                                                                  //获取当前线程名字
        System.out.println("当前线程是:" + Thread.currentThread().getName());

        for(int i = 0;i <100 ;i++) {
            System.out.println("thread1:" + i);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

MainClass中:

    MyThread myThread = new MyThread();
    myThread.setName("thread1");
    System.out.println("当前线程是:" + Thread.currentThread().getName());
     myThread.start();    //启动线程使用start

样例测试:


使用接口创建进程

  • 创建思路

    • 使用接口形式创建一个任务类,要交给一个线程去执行该任务。
  • 使用接口的优势

    • 1.使用接口的形式创建进程,可以让程序更灵活;
    • 2.强程序的健壮性,多次创建,可以被多个线程共享代码。

新建任务类MyTask:


public class MyTask implements Runnable{

        @Override
        public void run() {
                                //在run中写要在线程中执行的代码
                                //获取当前线程名字
        System.out.println("当前线程是:" + Thread.currentThread().getName());

        for(int i = 0;i <100 ;i++) {
            System.out.println(Thread.currentThread().getName() + i);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

MainCass中新添加代码:

        Thread t2 = new Thread(new MyTask(),"t2:");
        t2.start();

匿名内部类


        //匿名内部类:可以使用接口创建一个没有类名的类
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        },"t3:      ").start();

线程池

  • 为什么要使用线程池?

    • 1.节省资源 减少线程的数量和创建销毁进程的开销;
    • 2.合理的管理线程的分配;
  • 分类
    1.newCatchedThreadPool
    创建一个带有缓存的线程池
    优点:
    很灵活,弹性的线程管理,需要多少线程就给多大的线程池;
    缺点:
    如果线程无限增长,会导致内存溢出;

2.newFixedThreadPool
优点:
创建一个固定大小的线程池,超出的任务会在队列中等待;
缺点:
难以拓展,不支持自定义拒绝策略;

3.newScheduledThreadPool
优点:
支持周期性的执行任务,固定大小;
缺点:
单线程执行,一旦一个事务失败会影响其他任务;

4.newSingleThreadPool
优点:
能够顺序执行任务;
缺点:
不明白怎么设计的,可以使用对列来实现;

5.ThreadPoolExecutor
优点:上面所有的;
缺点:没有,只是定义比较复杂;


                                            //这个地方填上面的分类
ExecutorService fixPool = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 20; i++) {
                //execute:执行一个任务
           fixPool.execute(new MyRunnable());
       }
        //关闭线程池
        fixPool.shutdown();
  • 线程池中参数的意义:
    • corePOOLSize:核心池的大小
    • maximumPoolSize:池内线程的最大数量
    • keepAliveTime:(最大数量-核心池大小数量的)线程的存活时间
    • TimeUnit unit的unit:上述时间的单位
    • BlockingQueue:对列,小括号里是对列的大小 <>中是泛型.如果有任务需要等待线程执行,就会临时存储在这个对列中
    • RejectedExecutionHandler:拒绝策略

         ThreadPoolExecutor pool = new ThreadPoolExecutor(3,5,5, TimeUnit.SECONDS,new LinkedBlockingDeque<>(20));
                new ThreadPoolExecutor.CallerRunsPolicy() {
                };
         pool.execute(new MyRunnable());
  • 拒绝策略
    • 1.AbortPolicy:丢弃任务,并且抛出异常
    • 2.DiscardPolicy:丢弃任务,不抛异常
    • 3.DiscardOldestPolicy:丢弃对列最前面的任务,尝试重新执行
    • 4.CallerRunsPolicy:谁把任务给我的谁来执行

锁(sychronized)

  • 锁相关
    • 可以给类、方法、代码块加锁;
    • 加的是“互斥锁(排它锁)”

加锁

  • 如果关键字修饰方法:

    • 1.被修饰的方法称为同步方法,作用范围是整个方法;
    • 2.作用对象是调用这个方法的对象;
    • 3.当不同线程都访问同一个同步方法时,后来的会等待锁的释放;
  • 如果关键字修饰代码块:

    • 1.作用范围是被包住的代码;
    • 2.作用对象是调用这个代码段的对象;
  • 如果关键字修饰类或者静态方法:

    • 作用对象是这个类的所有对象;

样例测试:
新建Sthread类调用Runnable接口:


public class SThread implements Runnable {

        private static int count = 0;

        @Override
        //synchronized不会被继承
        public /*synchronized*/void run() {

            System.out.println("111111");
            synchronized (SThread.class) {//括号里SThread.class是当前的类 作用类型所有对象,前两个都是this
                for (int i = 0; i < 5; i++) {

                    System.out.println(Thread.currentThread().getName() + ":" + (count++));

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
}

新建SClass类作为主函数:



public class SClass {

    public static void main(String[] args) {
    SThread sThread = new SThread();
        new Thread(sThread,"t1").start();
        new Thread(sThread,"t2").start();
    }
}


工程及工具

工程

链接:https://pan.baidu.com/s/1i_y9emVMW70W1JPqyuN38Q
提取码:h3ci

posted @ 2019-03-20 08:47  仲夏今天也在写前端  阅读(171)  评论(0编辑  收藏  举报