• 《图解Java多线程设计模式》之一:基础


    一,什么是线程?
    1.java中把正在执行程序的主体称为线程。
    2.单线程:
    当我们在阅读程序时,会根据处理流程来阅读,比如:首先执行前面的语句,然后再执行后面的语句,我们试着用笔将执行顺序描画出来,会发现描画出来的是一条弯弯曲曲的长线。这条长线始终是一条,无论调方法还是执行复杂的逻辑,对于这种处理流程始终如一条线的程序,称之为单线程程序。在单线程程序中,在某一个时间点执行的处理只有一个。
    3.多线程
    多个线程同时执行
    3.应用场景
    客户端应用程序
    耗时的I/O处理
    多个客户端:同时处理多个客户端

    二,Thread类
    1.启动线程必须使用线程类

    public class MyThread extends Thread{
    
        public void run(){
            for(int i=0;i<100;i++){
                System.out.println("hello");        
            }
        }
    }

    新启动的线程的操作都编写在run方法中,新线程启动后,会调用run方法。当run方法执行结束后,线程也会跟着终止

    2.启动一个线程

    public class Main{
        public static void main(String[] args){
            MyThread t = new MyThread();//创建线程
            t.start();//启动线程
    
            for(int i = 0;i<100;i++){
                System.out.println("world");
            }
        }
    }

    理解:上面代码中有两个线程,首先执行main方法,这个一个主线程。当执行到 t.start()时,会开启一个新的线程,该线程打印hello。
      同时主线程继续向下执行,并打印world。这个程序运行着两个线程,所以这是一个多线程程序。

    注意:启动线程调用的是start方法,不是run方法。当调用start方法后,程序会在后台启动新的线程。然后由这个新线程调用run方法。
          start方法做了两件事,启动新线程,调用run方法

    public class PrintThread extends Thread {
        private String message;
        public PrintThread(String message){
            this.message = message;
        }
        public void run(){
            for (int i = 0; i <1000 ; i++) {
                System.out.println(message);
            }
        }
    }
    
    --------------------------------------------------------------------
    public class Test {
        public static void main(String[] args) {
            new PrintThread("aaa").start();
            new PrintThread("bbb").start();
        }
    }
    
    这里新开启了两个线程,aaa和bbb交替打印
    
    --------------------------------------------------------------------
    public class Test {
        public static void main(String[] args) {
            new PrintThread("aaa").run();
            new PrintThread("bbb").run();
        }
    }
    
    这里只是创建了两个对象,并调用对象的run方法,先打印aaa在打印bbb
    
    注意上面的区别

    三,创建线程的方式
    1.继承Thread类

    public class MyThread extends Thread{
    
        public void run(){
            for(int i=0;i<100;i++){
                System.out.println("hello");        
            }
        }
    }

    注意:Thread类本身实现了Runnable接口,并且持有run方法,但Thread类的run方法主体是空的,不执行任何操作。
      Thread类的run方法通常由子类run方法重写。

    2.实现Runnable接口

    public class MyRunnable implements Runnable{
        public void run(){
            for(int i = 0;i<100;i++){
                System.out.println("world");
            }
        }
    }
    ----------------------------------------------------------
    
    Runnable r = new MyRunnable();
    Thread t = new Thread(r);
    t.start();

    3.java.util.concurrent.ThreadFactory中的线程创建

    public class Main{
        public static void main(String[] args){
            Runnable r = new MyRunnable();
            ThreadFactory factory = Executors.defaultThreadFactory();
            factory.newThread(r).start();
    
            for(int i = 0;i<100;i++){
                System.out.println("good");
            }
        } 
    }

    四,线程的暂停

    Thread.sleep();
    sleep方法必须try...catch。因为sleep方法会抛出InterruptedException异常。InterruptedException异常能够取消线程的处理。
    五,线程的互斥处理
    防止多个线程同时操作同一个资源,引起结果和预期不相同。
    1.synchronized方法
    一个实例中的synchronized方法每次只能由一个线程运行。每个实例都拥有一个独立的锁。
    synchronized方法的使用的是对象锁,synchronized静态方法使用的是类的类对象的锁(MyThread.class)。他们两个锁不一样
    六,线程的协作
    1.等待队列
    所有实例拥有一个等待队列,他是在实例的wait方法执行后停止操作的线程的队列。就好比是为每一个实例准备的线程休息室
    2.wait方法:把线程放入等待队列
    执行了 obj.wait();当前线程就会暂停运行,并进入实例obj的等待队列中
    注意:若要执行wait方法,线程必须持有锁。但如果线程进入等待队列,就会释放实例的锁
    3.notify方法:从等待队列中取出线程
    执行了obj.notify(); obj的等待队列的一个线程就会被选中和唤醒,然后就会退出等待队列。若要执行notify方法,线程也必须要持有调用的实例的锁
    注意:notify唤醒的线程并不会在执行notify的一瞬间重新运行,因为在执行nofity的那一瞬间,执行notify的线程还持有锁,
    其他线程还无法获取这个实例的锁
    4.notifyAll方法:从等待队列中取出所有的线程
    obj.notifyAll();
    5.如果线程未持有锁的情况下调用wait,notify,notifyAll方法,会怎样?
    抛异常:IllegalMonitorStateException 

    七,线程的状态转移

    待续

  • 相关阅读:
    路由 懒加载 错误ChunkLoadError: Loading chunk 10 failed.
    ngzorro create创建对话框 对话框组件内 关闭父组件 create对话框
    一个解决方案对dll的引用要注意的问题
    工作流的麻烦
    winform程序中使用documentview模式的考虑
    仿淘宝网评价的五角星投票代码
    图片闪烁代码
    JS+CSS仿淘宝滑过小图预览大图代码
    JavaScript控制图片左右播放的幻灯片代码
    JavaScript实现图片旋转构成3D圆环代码
  • 原文地址:https://www.cnblogs.com/inspred/p/9369606.html
Copyright © 2020-2023  润新知