• 多线程


    一、创建线程

           1.1 继承Thread

           步骤:1、自定义异常类继承Thread类

                    2、重写run()方法

                    3、创建线程对象

                    4、启动线程:线程对象.start();

          1.2 实现Runnable接口(注意也可以是匿名内部类的方式)

           步骤:1、自定义类实现Runnable接口

           2、重写run();方法

                    3、创建自定义类对象(注意:这不是一个线程对象,只有继承Thread的子类才是线程类)

                    4、创建线程,使用Thread(Runnable target)构造器,将自定义类对象作为参数传递。

                    5、启动线程:线程对象.start();

    二、Thread类

           2.1 常用构造方法

                  Thread()

        Thread(String name)

                  Thread(Runnable target)

                  Thread(Runnable target, String name)  

           2.2 常用方法

                  static Thread currentThread()  :返回当前线程对象

                  String getName() :返回该线程的名称。

                  int getPriority(): 返回线程的优先级。

                  void setPriority(int newPriority) :更改线程的优先级。

                  Thread.State getState()返回该线程的状态,状态是枚举类。

                  boolean isDaemon() :测试该线程是否为守护线程。

                  void setDaemon(boolean on) :将该线程标记为守护线程或用户线程。

                  void join() :某个线程调用该方法加入到另一个线程中,另一个线程等待该线程执行完毕后再继续执行。

                  void run() :里面写业务

                  static void sleep(long millis) :正在执行的线程休眠

                  void start() :使该线程开始执行,执行run方法

                  static void yield() :暂停当前正在执行的线程对象,并执行其他线程。

    三、线程同步

    加锁原则:尽可能缩小加锁的范围,提高程序效率

           3.1 同步代码块

                  synchronize(同步监听对象){

                      需要被同步的代码

                  }

                  注意:监听对象可以是任意的,但是要保证多个线程访问到的是同一个对象。常用当前类的字节码对象。

           3.2 同步方法

                  使用synchronize修饰方法,放在返回值类型前面,不需要写同步监听对象,实例方法默认监听对象是this,静态方法默认监听对象是当前类的字节码对象。

           注意:继承的方式的话,建议使用同步代码块,因为this不是同一个对象,虽然通过static修饰方法是可以的,但是这样不好,一般static用于工具类方法。

           3.3 锁机制

           通过:private final ReentrantLock lock = new ReentrantLock();//创建锁对象

           语法:lock.lock();  //加锁

                    try {

                         //需要同步的代码

                       } finally {

                                //通常释放资源                 

                                lock.unlock();//解锁

                       }

           注意:1、这种方式和前面两种方式一样,必须保证锁是同一个对象。(继承方式需要static修饰锁,实现不需要)

    四、线程通信

    三个方法:   均是Object方法

           void wait() :调用该方法线程等待,直到被唤醒

           void notify() :唤醒在此对象监视器上等待的单个线程。

           void notifyAll():唤醒在此对象监视器上等待的所有线程。

    /**
     * 三个线程分别打印A、B、C,实现ABCABCABC交替打印 思路,打印任意一个字母的时候,其他两个线程阻塞
     * 问题:1、为什么监视对象不能使用PrintABC.class?
     *     2、为什么是while,不是if?
     *     3、为什么匿名内部类访问外部变量时final修饰,怎么理解?
     *     4、谁调用wait方法,如何理解?
     * 自己的理解:三个方法三个锁锁住,但是需要同一个锁才能将他们联系起来,如果一开始用PrintABC.class作为监视对象的话,能锁住,但是没办法调用
     * wait和notify方法,如果用this作为监视对象,三个线程中是this是当前的Runnable对象(就近原则),所以也是不同的。
     */
    public class PrintABC {
    
        // 创建3个打印标志,判断当前打印谁,一次只能打印一个
        public static boolean isThreadA = true;
        public static boolean isThreadB = false;
        public static boolean isThreadC = false;
    
        public static void main(String[] args) {
            final PrintABC abc = new PrintABC();
            // 打印A
            new Thread(new Runnable() {
    
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {// 打印10次
                        synchronized (abc) {
                            while(!isThreadA) {
                                try {
                                    abc.wait();// 阻塞
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            System.out.println("A");
                            // 修改三个标志
                            isThreadA = false;
                            isThreadB = true;
                            isThreadC = false;
                            abc.notifyAll();
                        }
                    }
                }
            }).start();
    
            // 打印B
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        synchronized (abc) {
                            while(!isThreadB) {
                                try {
                                    abc.wait();// 阻塞
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            System.out.println("B");
                            isThreadA = false;
                            isThreadB = false;
                            isThreadC = true;
                            abc.notifyAll();
                        }
                    }
                }
            }).start();
    
            // 打印C
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        synchronized (abc) {
                            while(!isThreadC) {
                                try {
                                    abc.wait();// 阻塞
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                            System.out.println("C");
                            isThreadA = true;
                            isThreadB = false;
                            isThreadC = false;
                            abc.notifyAll();
                        }
                    }
                }
            }).start();
        }
    
    }

    五、Timer类 

      常用于定时任务,如 闲时上传等

      构造器:Timer()

      配合TimerTask类使用
       TimerTask:抽象类,使用方式:
          1. 写一个子类继承 重写run方法(定时任务)
          2. 匿名内部类 语法
            new TimerTask(){
               @Override
                run(){
                定时任务
                }
            };

      常用方法:

      1.void schedule(TimerTask task, Date time)
        安排在指定的时间执行指定的任务。
      2.void schedule(TimerTask task, Date firstTime, long period)
        安排指定的任务在指定的时间开始进行重复的固定延迟执行。
      3.void schedule(TimerTask task, long delay)
        安排在指定延迟后执行指定的任务。
      4.void schedule(TimerTask task, long delay, long period)
        安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。
      5.void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
        安排指定的任务在指定的时间开始进行重复的固定速率执行。
      6.void scheduleAtFixedRate(TimerTask task, long delay, long period)
        安排指定的任务在指定的延迟后开始进行重复的固定速率执行。

  • 相关阅读:
    cmake常用工程示例大集合
    qt---cdb(Microsoft Console Debugger)调试
    Qt Creator设置多核编译(-j8参数)
    这都是些老观点了。世界在变,时代在变。中国人观念进步的更快
    微软全球执行副总裁沈向洋:三年内用人工智能赚100亿美元
    C# 6.0
    node.js + mongodb
    分布式消息系统kafka
    jQuery插件开发
    jqgrid-asp.net-mvc
  • 原文地址:https://www.cnblogs.com/zwcnblog/p/9910989.html
Copyright © 2020-2023  润新知