• java之Thread


         * 线程:程序执行的一条路径,一个进程可以包含多条线程
         * 多线程并发执行可以提高程序的效率,可以同时完成多个工作
         *
         * JVM的启动至少启动了垃圾回收线程和主线程两个线程,所以是多线程;
         *
         * 多线程的实现方式有2中:
         *    1. 继承Thread
         *      1) 定义类继承Thread
         *      2) 重写run方法
         *      3) 把新线程要做的事写在run方法中
         *      4) 创建线程对象
         *      5) 开启新线程,内部会自动执行run方法

    创建线程的第一种方式:继承Thread类

     1 public static void main(String[] args) {
     2 
     3         MyThread mt = new MyThread();   // 4) 创建线程对象
     4         mt.start();                     // 5) 开启新线程,内部会自动执行run方法
     5         for(int i = 0; i < 3000; i++) {
     6             System.out.println("bb");
     7         }
     8     }
     9 
    10 }
    11 
    12 class MyThread extends Thread {     // 1) 定义类继承Thread
    13     public void run() {             // 2) 重写run方法
    14         for(int i = 0; i < 3000; i++) {     // 3) 把新线程要做的事写在run方法中
    15             System.out.println("aaaaaaaaaaaaaaaa");
    16         }
    17     }
    18 }

    创建线程的第2中方式:实现Runnable接口     * 实现多线程的第2中方式,实现Runnable接口:
         *       1. 创建类实现Runnable接口
         *    2. 重写run方法,将要执行的代码写入run方法中
         *    3. 创建自定义类的对象
         *    4. 创建Thread类对象,将自定义对象传入
         *    5. Thread类对象调用start方法开启新线程,内部会自动调用Runnnable中的run方法

     1     public static void main(String[] args) {
     2 
     3         MyRunnable mr = new MyRunnable();
     4         Thread t = new Thread(mr);
     5         t.start();
     6         for(int i = 0; i < 3000; i++) {
     7             System.out.println("bbb");
     8         }
     9     }
    10 
    11 }
    12 
    13 class MyRunnable implements Runnable{
    14 
    15     @Override
    16     public void run() {
    17         for(int i = 0; i < 3000; i++) {
    18             System.out.println("aaaaaaaaaaaa");
    19         }
    20     }
    21     
    22 }

     两种方式的区别:
         *    1. 查看源码的区别
         *        a. 继承Thread:由于子类重写了Thread类的run(),当调用start()方法时,直接找子类的run()方法
         *      b. 实现Runnable:构造函数中传入了Runnable的引用,成员变量记住了它,start()调用run()方法时内部判断成员变量Runnabe的引用是否为空,
         *         如果不为空,编译时看的是Runnable的run(),运行时执行的是子类的run()方法
         *         
         *    2. 实现使用上的区别:
         *      继承Thread:
         *         a.好处:可以直接使用Thread类中的方法,代码简单
         *         b.弊端:如果已经有了父类,就不能使用这种方法
         *      实现Runnable接口
         *         a.好处:即使自己定义的线程类有了父类也没有关系,因为有了父类可以实现接口,而且接口是可以多实现的
         *         b.弊端:不能直接使用Thread中的方法,需要先获取到线程对象后,才能得到Thread的方法,代码复杂  

    使用匿名内部类实现多线程的两种方式:

     1 public static void main(String[] args) {
     2 
     3         new Thread() {
     4             public void run() {
     5                 for(int i = 0; i < 3000; i++) {
     6                     System.out.println("aaaaa");
     7                 }
     8             }
     9         }.start();
    10         
    11         new Thread(new Runnable() {
    12             public void run() {
    13                 for(int i = 0; i < 3000; i++) {
    14                     System.out.println("bb");
    15                 }
    16             }
    17         }).start();
    18     }

    给线程设置名称两种方式:

          1.  使用构造方法

          2.  使用setName()方法

     1 public class Demo4_ThreadMethod {
     2 
     3     /*
     4      * 设置线程名字的两种方法:
     5      *    1. 构造方法
     6      *    2. setName()方式
     7      */
     8     public static void main(String[] args) {
     9 
    10         //demo1();
    11         //demo2();
    12         //demo3();
    13         Thread t = new Thread() {
    14             public void run() {
    15                 System.out.println(this.getName() + "...ccc");
    16             }
    17         };
    18         t.setName("王五");
    19         t.start();
    20     }
    21 
    22     /**
    23      * 通过setName()方法给线程名赋值
    24      */
    25     public static void demo3() {
    26         new Thread() {
    27             public void run() {
    28                 this.setName("李四");
    29                 System.out.println(this.getName() + "...bb");
    30             }
    31         }.start();
    32     }
    33 
    34     /**
    35      * 通过构造方法给线程名称赋值
    36      */
    37     public static void demo2() {
    38         new Thread("张三") {
    39             public void run() {
    40                 System.out.println(this.getName() + "...aaa");
    41             }
    42         }.start();
    43     }
    44 
    45     /**
    46      * 线程的名称是默认从0  Thread-0  依次往后累加
    47      */
    48     public static void demo1() {
    49         new Thread() {
    50             public void run() {
    51                 System.out.println(this.getName() + "...aaa");  //Thread-0...aaa   
    52             }
    53         }.start();
    54     }
    55 
    56 }

    currentThread()方法和sleep()方法的使用:

     1 public class Demo5_CurrentThread {
     2 
     3     /*
     4      * CurrentThread()方法用来获取当前正在执行的线程
     5      * 
     6      * sleep()方法:会使线程暂时停一段时间
     7      */
     8     public static void main(String[] args) {
     9 
    10         new Thread() {
    11             public void run() {
    12                 System.out.println(getName() + "...bbb");
    13             }
    14         }.start();
    15         
    16         new Thread(new Runnable() {
    17             public void run() {
    18                 Thread.currentThread().setName("李四");    
    19                 //由于Runnable接口没有setName() 和 getName()方法,所以需要用currentThread()方法获取当前线程
    20                 System.out.println(Thread.currentThread().getName() + "...aaa");
    21             }
    22         }).start();
    23     }
    24 
    25 }

    守护线程:

     1 public class Demo6_Daemon {
     2 
     3     /*
     4      * 守护线程
     5      */
     6     public static void main(String[] args) {
     7 
     8         Thread t1 = new Thread() {
     9             public void run() {
    10                 for(int i = 0; i < 2; i++) {
    11                     System.out.println(getName() + "...aaaa");
    12                 }
    13             }
    14         };
    15         
    16         Thread t2 = new Thread() {
    17             public void run() {
    18                 for(int i = 0; i < 50; i++) {
    19                     System.out.println(getName() + "...bb");
    20                 }
    21             }
    22         };
    23         
    24         t2.setDaemon(true);    //设置t2为守护线程,当t1结束时t2也会随之结束
    25         t1.start();
    26         t2.start();
    27     }
    28 
    29 }

    join()方法的使用:

     1 public class Demo7_Join {
     2 
     3     /*
     4      * join()插队,等另外一个线程执行完毕后,再接着执行
     5      * join(1)插队1毫秒,1毫秒后两个线程继续交替执行
     6      */
     7     public static void main(String[] args) {
     8         final Thread t1 = new Thread() {
     9             public void run() {
    10                 for(int i = 0; i < 10; i++) {
    11                     System.out.println(getName() + "...aaa");
    12                 }
    13             }
    14         };
    15         
    16         Thread t2 = new Thread() {
    17             public void run() {
    18                 for(int i = 0; i < 10; i++) {
    19                     if(i==2) {
    20                         try {
    21                             //t1.join();             //匿名内部类要想调用局部变量,需要局部变量声明为final类型的
    22                             t1.join(1);              //t1加入1毫秒,1毫秒后两个接着交替执行
    23                         } catch (InterruptedException e) {
    24                             e.printStackTrace();
    25                         }
    26                     }
    27                     System.out.println(getName() + "...bb");
    28                 }
    29             }
    30         };
    31         t1.start();
    32         t2.start();
    33     }
    34 }

    同步的使用:

    public class Demo8_Sychronized {
    
        /*
         * 同步代码块中需要传入的锁对象可以是任何对象,但是不能是匿名对象
         * 
         * 静态同步方法中的锁对象是类的字节码对象,如:demo.class
         */
        public static void main(String[] args) {
    
            Object o = new Object();
            while(true) {
                synchronized(o) {
                    System.out.print("t");
                    System.out.print("e");
                    System.out.print("s");
                    System.out.print("t");
                    System.out.println();
                }
                
                synchronized(o) {
                    System.out.print("a");
                    System.out.print("b");
                    System.out.print("c");
                    System.out.print("d");
                    System.out.println();
                }
            }
        }
    
    }

    练习:

           4个窗口同时售100张火车票

     1 继承Thread类的方式
     2 
     3 public class Demo9_Ticket {
     4 
     5     /*
     6      * 四个窗口同时卖出100张票
     7      */
     8     public static void main(String[] args) {
     9 
    10         new Ticket().start();
    11         new Ticket().start();
    12         new Ticket().start();
    13         new Ticket().start();
    14     }
    15 
    16 }
    17 
    18 class Ticket extends Thread{
    19     private static int ticket = 100;
    20     //private static Object o = new Object();   如果是使用这种成员变量的方式,需要声明为静态变量
    21     public void run() {
    22         while(true) {
    23             synchronized(Ticket.class) {
    24                 if(ticket <= 0) {
    25                     break;
    26                 }
    27                 try {
    28                     Thread.sleep(10);
    29                 } catch (InterruptedException e) {
    30                     e.printStackTrace();
    31                 }
    32                 System.out.println(getName() + "...第" + ticket-- + "张票");
    33             }
    34         }
    35     }
    36 }
    37 
    38 ------------------------------------------
    39 
    40 实现Runnable接口的方式:
    41 
    42 public class Demo10_Ticket {
    43 
    44     /*
    45      * 使用实现Runnable接口进行四个窗口同步卖票
    46      */
    47     public static void main(String[] args) {
    48 
    49         Ticket1 t = new Ticket1();
    50         new Thread(t).start();
    51         new Thread(t).start();
    52         new Thread(t).start();
    53         new Thread(t).start();
    54         
    55         /*Ticket1 t1 = new Ticket1();
    56         Thread t2 = new Thread(t1);
    57         t2.start();
    58         t2.start();
    59         t2.start();
    60         t2.start();
    61         一个线程只能启动一次,调用一次start()方法
    62         */
    63     }
    64 
    65 }
    66 
    67 class Ticket1 implements Runnable{
    68 
    69     private int ticket = 100;
    70     @Override
    71     public void run() {
    72         while(true) {
    73             synchronized(this) {
    74                 if(ticket<=0) {
    75                     break;
    76                 }
    77                 try {
    78                     Thread.sleep(10);
    79                 } catch (InterruptedException e) {
    80                     e.printStackTrace();
    81                 }
    82                 System.out.println(Thread.currentThread().getName() + "...第" + ticket-- + "张票");
    83             }
    84         }
    85     }
    86     
    87 }
  • 相关阅读:
    BZOJ 1051: [HAOI2006]受欢迎的牛( tarjan )
    BZOJ 2208: [Jsoi2010]连通数( DFS )
    js效果-鼠标提示框
    CSS-背景
    CSS-文本
    tomcat 安装 for Mac
    CSS选择器基础
    POJ3349-Snowflake Snow Snowflakes-Hash
    数据库的三大设计范式
    HDU5120-Intersection-两个圆环相交面积
  • 原文地址:https://www.cnblogs.com/jiangjunwei/p/Thread.html
Copyright © 2020-2023  润新知