zoukankan      html  css  js  c++  java
  • 浅析线程进程相关的知识点

    1.线程、进程

    1.1 概念

    进程:引入:为了程序能够并发执行,且为了对并发执行的程序加以描述和控制,引入了进程的概念。

      (1)进程是程序的一次执行。

      (2)进程是一个程序及其数据在处理机上顺序执行时所发生的活动。

      (3)进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。 

      (4)进程是作为能够拥有资源和独立运行的基本单位。

    线程:  引入:在操作系统中引入线程,是为了减少程序并发执行时锁付出的空间开销,使OS具有更好的并发性。1.2

    1.2 线程与进程进行比较

      线程具有许多传统进程所具有的特征,所以又称为轻量级进程或进程元,相应的把进程称为重量级的进程,传统进程相当于只有一个线程的任务,在引入了新城的操作系统中,通常一个进程都拥有若干个线程,至少也有一个线程。

      相同点:

      (1)调度:

      (2)并发性:在引入了线程的操作系统中,进程之间或一个线程中的多个线程之间都可以并发执行。

      (3)拥有资源:不论是传统的操作系统还是引入了线程的操作系统,进程都可以拥有资源,是系统中拥有资源的有个基本单位。

      (4)系统开销:在某些操作系统中,线程的切换、同步和通信都无需操作系统内核的干预。

      不同点

      (1)调度:在传统操作系统中,进程是拥有资源的基本和独立调度、分派的基本单位,在引入了线程的操作系统中,线程是调度和分派的基本单位,而进程是拥有资源的基本单位。

      (2)并发性:

      (3)拥有资源:进程拥有资源,线程自己不拥有资源(也有一点必不可少的资源)。但可以吧访问其他隶属进程的资源。

      (4)系统开销:

        a.在创建或撤销进程的时候,系统都要为之创建和回收进程控制块,分配或回收资源。如内存空间和I/O设备,系统开销明显大于线程创建或撤销时的开销。

        b.在进程切换时,涉及到当前进程CPU环境的保存及新被调度运行进程的CPU环境的设置,而线程的切换则仅需要保存和设置少量寄存器内容,不涉及存储器管理方面的操作,所以,进程的代价远高于线程。

        c.一个进程的多个线程具有相同的地址空间,在同步和通信的实现方面线程也比进程容易。

      (5)进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

      (6)进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮。

      (7)每个独立的线程都有一个程序运行的入口,顺序执行序列和程序的入口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

    1.3 线程的生命周期

    1.3.1.线程处于就绪状态有以下几种方法

      (1)调用sleep()方法

      (2)调用wait()方法

      (3)等待输入/输出完成

    1.3.2.当线程处于就绪状态后,可以用以下几种方法使线程进入运行状态:

      (1)线程调用notify()方法

      (2)线程调用notifyAll()方法

      (3)线程调用interrupt()方法

      (4) 线程的休眠时间结束

      (5)输入/输出结束

      线程生命周期状态图:

                  

    2.线程的调度与控制

    2.1 线程优先级

      java虚拟机主要负责则线程的调度,获取CPU的使用权,目前有两种调度模型:分时调度模型和抢占调度模型;java使用抢占调度模型。

      分时调度模型:所有线程轮流使用CPU的使用权,平均分配给每个线程占用CPU的时间片。

      抢占调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么随机选择一个,优先极高的线程获得的CPU时间片相对多些。

          例:

     1 /*
     2    线程优先级高的获取的时间片相对高
     3 */
     4 class  Threadtest04
     5 {
     6     public static void main(String[] args) 
     7     {
     8         //线程优先级
     9         System.out.println(Thread.MAX_PRIORITY); //10 优先级最高
    10         System.out.println(Thread.MIN_PRIORITY); //1  优先级最低
    11         System.out.println(Thread.NORM_PRIORITY); //5  默认优先级
    12         Thread t1 = new P();
    13         t1.setName("t1");
    14 
    15         Thread t2 = new P();
    16         t2.setName("t2");
    17 
    18         System.out.println(t1.getPriority()); //默认优先级为5
    19         System.out.println(t2.getPriority()); //默认优先级为5
    20         //设置优先级
    21         t1.setPriority(4);
    22         t2.setPriority(9);
    23 
    24         System.out.println(t1.getPriority()); //默认优先级为5
    25         System.out.println(t2.getPriority()); //默认优先级为5
    26         //启动线程
    27         t1.start();
    28         t2.start();
    29     }
    30 }
    31 
    32 class P extends Thread
    33 {
    34     public void run()
    35     {
    36         for(int i=0;i<10;i++)
    37         {
    38             System.out.println(Thread.currentThread().getName()+"..."+i);
    39         }
    40     }
    41 }
    42 /*
    43 运行结果:
    44 10
    45 1
    46 5
    47 5
    48 5
    49 4
    50 9
    51 t1...0
    52 t2...0
    53 t1...1
    54 t2...1
    55 t1...2
    56 t2...2
    57 t1...3
    58 t2...3
    59 t1...4
    60 t2...4
    61 t1...5
    62 t2...5
    63 t1...6
    64 t2...6
    65 t1...7
    66 t2...7
    67 t1...8
    68 t2...8
    69 t1...9
    70 t2...9
    71 请按任意键继续. . .
    72 
    73 
    74 */
    View Code

    2.2 sleep方法

      sleep和wait的区别:

          (1)所属类不同  

                   Thread.sleep() ;   Object.wait()

          (2)对于线程已经占有资源的处理

                  sleep在休息的时候,不释放资源 ; wait在等待的时候释放自己占用的资源

      例:

     1 /*
     2   1.thread.sleep(毫秒)
     3   2.sleep方法是一个静态方法
     4   3.该方法作用:阻塞当前线程,将CPU让给其他线程
     5 */
     6 class Threadtest05 
     7 {
     8     public static void main(String[] args) throws InterruptedException
     9     {
    10         Thread t1 = new P();
    11         t1.setName("t1");
    12         t1.start();
    13         Thread.sleep(5000);
    14         //t1.interrupt();打断线程的睡眠
    15         for(int i = 0;i<10;i++)
    16         {
    17             System.out.println(Thread.currentThread().getName()+".."+i);
    18             Thread.sleep(500);//阻塞主线程0.5秒
    19         }
    20     }
    21 }
    22 
    23 class P extends Thread
    24 {
    25     //被重写的方法不能抛出异常,在run方法的声明为置上不能呢使用Throws,
    26     public void run()
    27     {
    28         for(int i = 0;i<10;i++)
    29         {
    30             
    31             try{
    32                 Thread.sleep(1000);//让当前线程阻塞1s
    33             }catch(InterruptedException e)
    34             {
    35                 e.printStackTrace();
    36             }
    37             System.out.println(Thread.currentThread().getName()+".."+i);
    38         }
    39     }
    40 }
    41 /*
    42   运行结果:
    43   main..0
    44 t1..0
    45 main..1
    46 t1..1
    47 main..2
    48 main..3
    49 main..4
    50 t1..2
    51 main..5
    52 t1..3
    53 main..6
    54 main..7
    55 t1..4
    56 main..8
    57 main..9
    58 t1..5
    59 t1..6
    60 t1..7
    61 t1..8
    62 t1..9
    63 请按任意键继续. . .
    64 
    65 */
    View Code

    2.3 yield方法

      使用yield方法,与sleep方法类似,不能由用户指定暂停多长时间,并且yield方法只能让同优先级的线程由执行机会,让位时间不固定。静态方法

    2.4 Join方法

      合并线程

    3.创建线程的三种方法

      Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用三种方式来创建线程,如下所示:

      (1)继承Thread类创建线程

      (2)实现Runnable接口创建线程

      (3)使用Callable和Future创建线程

    3.1.概念及特点

      (1).概念

      进程:计算机运行的应用程序。(多进程作用:提高CPU的使用率,不提高速度);

      线程;一个进程中的执行场景,一个进程可以包多个线程。(多线程作用:提高应用程序的使用率,不提高速度)。

      (2).内存特点

      进程和进程之间的内存是独立的;

      线程和线程共享“堆内存的方法区内存”,栈内存是独立的,一个线程一个栈。

      (3).java程序的运行原理

      Java命令启动Java虚拟机,启动JVM,等同于启动了一个应用程序,表示启动了一个进程,该进程会自动启动一个“主线程”,然后主线程去调用某个类的main方法,所 以main方法运行在主线程中。

    3.2 线程的创建和启动

    3.2.1 实现多线程的第一种方式

      Thread类在包java.lang中,从这个类中实例化的对象代表线程,启动一个新线程需要建立Thread实例,Thread类中常用的两个构造方法如下:

      (1)public Thread(String threadName)

      (2)public Thread()

      其中第一个构造方法是创建一个名称为threadName的线程对象

      创建一个新的线程的语法如下:

     public class ThreadTest extends Thread{}

      完成线程真正功能的代码方法类run()方法中,当一个类继承Thread类后,就可以在该类中覆盖run方法,将实现该线程功能的代码写入run()方法中国,然后调用Thread类中的start()方法执行线程,即调用run()方法.

      Thread对象需要一个任务来执行,任务是指线程在启动时执行的工作,该工作的功能代码被写在run()方法中。当执行一个线程程序时,就自动产生一个线程,主方法是在这个线程上运次的,当不再启动其他线程时,该程序就为单线程程序。

       以下是一个Thread类的实例:

    /**
     * 类ThreadTest继承继承Thread雷诺方法创建线程
     * @author z
     *
     */
    public class ThreadTest extends Thread {
       private int count = 10;
       public void run(){
           while(true){
               System.out.println(count+"");
               if(--count == 0){
                   return;
               }
           }
       }
        public static void main(String[] args){
            new ThreadTest().start();
            
        }
     }

      运行结果:10 9 8 7 6 5 4 3 2 1

      分析:

      在上例中,继承了Thread类,然后覆盖了run()方法,通常在run()方法中使用无限循环的形式,使得线程一直运行下去,所以要指定一跳出循环的条件,本例使用变量count递减为0的方法跳出循环条件。

      在main()方发中,使线程执行需要调用Thread类中的start()方法,start()方法调用被覆盖的run()方法,如果不调用start()方法,线程永远不会启动,在主方法没有调用stsrt()方法之前,Thread()对象只是一个实例,而不是一个正真的线程。

           再举一个例子:

      第一步: 继承Java.lang.Thread

      第二步;重写run方法

      例:

     1 class  Threadtest01
     2 {
     3     public static void main(String[] args)   //main方法在主线程
     4     {
     5         //1.创建线程
     6         Thread t = new p();
     7         //2.启动线程
     8         t.start();      /*启动t线程,执行后,t线程瞬间结束,JVM再分配一个新的栈给t线程
     9                           run方法不需要手动调用,系统线程启动之后自动调用run方法。*/
    10     
    11        for(int i=0;i<100;i++)   //在主线程中运行
    12         {
    13            System.out.println("main....."+i);
    14         }
    15     }
    16 }
    17 /*
    18    在多线程中,main方法结束后只是主线程踪没有方法栈帧了,但
    19    其他线程中或者其他栈中还有栈帧,main方法结束,程序可能还在运行
    20 */
    21 
    22 //3.定义一个线程
    23 class p extends Thread
    24 {
    25     //重写run方法
    26     public void run ()
    27     {
    28          for(int i=0;i<100;i++)
    29         {
    30            System.out.println("run...."+i);
    31         }
    32     }
    33 }
    34 /*
    35 运行部分结果如下:
    36 main.....0
    37 main.....1
    38 main.....2
    39 run....0
    40 main.....3
    41 run....1
    42 main.....4
    43 run....2
    44 main.....5
    45 run....3
    46 main.....6
    47 run....4
    48 main.....7
    49 run....5
    50 main.....8
    51 run....6
    52 */
    View Code

      上述代码的图解如下:

    3.3.2 实现多线程的第二种方式:

      Runnable接口的说用是使线程不仅可以继承Thread类实现,还可以继承其他类(比如:JFrame)。

      此接口具有两个构造方法:

      (1)public Thread(Runnable r)

      (2)public Thread(Runnable r,String name).

      这两个构造方法的参数中都存在Runnable实例,使用构造方法就可以将Runnable实例与Thread实例相关联。

      使用Runnable的步骤如下:

      (1)建立Runnable对象

      (2)使用参数为Runnable对象的构造方法创建Thread实例

      (3)调用start()方法。

      例:在项目中创建SwingAndThread类,该类继承了JFrame类,实现图标移动的功能,其中使用了Swing与线程相结合的技术:

     1 import java.awt.*;
     2 import java.net.*;
     3 
     4 import javax.swing.*;
     5 
     6 public class SwingAndThread extends JFrame {
     7     /**
     8      * 
     9      */
    10     private static final long serialVersionUID = 1L;
    11     private JLabel jl = new JLabel(); // 声明JLabel对象
    12     private static Thread t; // 声明线程对象
    13     private int count = 0; // 声明计数变量
    14     private Container container = getContentPane(); // 声明容器
    15     
    16     public SwingAndThread() {
    17         setBounds(300, 200, 250, 100); // 绝对定位窗体大小与位置
    18         container.setLayout(null); // 使窗体不使用任何布局管理器
    19         URL url = SwingAndThread.class.getResource("/1.gif"); // 获取图片的URL
    20         Icon icon = new ImageIcon(url); // 实例化一个Icon
    21         jl.setIcon(icon); // 将图标放置在标签中
    22          // 设置图片在标签的最左方
    23         jl.setHorizontalAlignment(SwingConstants.LEFT);
    24         jl.setBounds(10, 10, 200, 50); // 设置标签的位置与大小
    25         jl.setOpaque(true);
    26         t = new Thread(new Runnable() { // 定义匿名内部类,该类实现Runnable接口
    27                     public void run() { // 重写run()方法
    28                         while (count <= 200) { // 设置循环条件
    29                              // 将标签的横坐标用变量表示
    30                             jl.setBounds(count, 10, 200, 50);
    31                             try {
    32                                 Thread.sleep(1000); // 使线程休眠1000毫秒
    33                             } catch (Exception e) {
    34                                 e.printStackTrace();
    35                             }
    36                             count += 4; // 使横坐标每次增加4
    37                             if (count == 200) {
    38                                 // 当图标到达标签的最右边,使其回到标签最左边
    39                                 count = 10;
    40                             }
    41                         }
    42                     }
    43                 });
    44         t.start(); // 启动线程
    45         container.add(jl); // 将标签添加到容器中
    46         setVisible(true); // 使窗体可视
    47         // 设置窗体的关闭方式
    48         setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    49     }
    50     
    51     public static void main(String[] args) {
    52         new SwingAndThread(); // 实例化一个SwingAndThread对象
    53     }
    54 }
    View Code

      运行结果:

      

      再举一个例子:

      第一步:写一个实现类java,lang.Runnable;接口

      第二步:实现run方法

      例:

     1 package test;
     2 
     3 class Main 
     4 {
     5     public static void main(String[] args) 
     6     {
     7         //创建线程
     8         Thread t = new Thread(new p());
     9         //启动线程
    10         t.start();
    11         for(int i = 0;i<100;i++)
    12               System.out.println("mian..."+i);
    13         
    14     }
    15 }
    16 //优先,一个类实现接口之外保留了类的继承
    17 class p implements Runnable
    18 {
    19     public void run()
    20     {
    21         for(int i = 0;i<100;i++)
    22           System.out.println("run..."+i);
    23     }
    24 }
    25 /*
    26  * 部分运行结果:
    27  * run...8
    28 mian...10
    29 run...9
    30 mian...11
    31 run...10
    32 mian...12
    33 run...11
    34 mian...13
    35 run...12
    36  */
    View Code

    4.线程的同步(加锁)

    4.1 基本概念及特点

    (1)概念:

      a.线程同步,是指某一个时刻,只允许一个线程访问共享资源,线程同步实际上是对对象加锁,如果对象中的方法都是同步方法,那么某一时刻只能执 行一个方法,采用线程同步解决以上问题;  为了数据安全,尽管应用程序的使用效率降低,但是为了数据安全,必须加入线程同步机制,线程同步机制使程序等同于单线程。

      b.异步编程模型:多个线程分别执行,各线程互不影响。

      c.同步编程模型:多个线程执行只有一个线程执行结束才能执行另一个线程。(作用:达到数据安全)

    (2)使用线程同步机制的条件:

      a:必须是多线程环境

      b:多线程环境共享一个数据

      c:共享的数据涉及到数据的修改

    4.2 举例

      例1:(对象锁,方法一,控制精确,常用)

     1 /*
     2    模拟银行取款系统:对于同一个账号,用两个线程同时对其取款。
     3 */
     4 class Threadtest06
     5 {
     6     public static void main(String[] args) 
     7     {
     8        //创建公共账号
     9        Account act = new Account("账号sss",10000);
    10        //创建两个线程对同一个账户取款
    11        Thread t1 = new Thread(new P(act));
    12        Thread t2 = new Thread(new P(act));
    13        t1.start();
    14        t2.start();
    15     }
    16 }
    17 //取款线程
    18 class P implements Runnable
    19 {
    20     //账户
    21     Account act;
    22     P(Account act)
    23     {
    24         this.act = act;
    25     }
    26     public void run()
    27     {
    28         act.withdraw(2000);
    29         System.out.println("取款成功,余额为:"+act.getBalance());
    30     }
    31 
    32 }
    33 //账户
    34 class Account
    35 {
    36     private String action;
    37     private double balance;
    38     public Account(){}
    39     public Account(String action,double balance){
    40       this.action = action;
    41       this.balance = balance;
    42     }
    43     public void setAction(String action)
    44     {
    45         this.action = action;
    46     }
    47     
    48     public void setBalance(double balance)
    49     {
    50         this.balance = balance;
    51     }
    52     public String getAction(String action)
    53     {
    54         return action;
    55     }
    56     public double getBalance()
    57     {
    58         return balance;
    59     }
    60     public void withdraw(double money)
    61     {
    62         synchronized(this){  //this表示共享对象
    63            double after = balance - money;
    64            try{
    65            Thread.sleep(1000);
    66            }catch(Exception e){}
    67            this.setBalance(after);
    68         }
    69     }
    70 }
    71 
    72 /*
    73 运行结果:
    74 取款成功,余额为:8000.0
    75 取款成功,余额为:6000.0
    76 请按任意键继续. . .
    77 
    78 */
    View Code

      上例原理:   t1线程执行到synchronized关键字处,就会去找this对象锁,如果找到this对象锁,就回进入同步语句块中执行,当同步语句块中的代码执行结束后,

      t1线程归还this对象锁。在t1线程执行同步语句块的过程中,如果t2线程也过来执行此代码,也遇到synchronized关键字,所以也去找this对象锁,但是

      该对象锁被t1线程持有,只能等待this对象的归还。

      例2;synchronized关键字添加到成员方法上,线程拿到的扔是this的对象锁(对象锁,方法二,执行效率低)

     1 /*
     2    模拟银行取款系统:对于同一个账号,用两个线程同时对其取款。
     3 */
     4 class Threadtest06
     5 {
     6     public static void main(String[] args) 
     7     {
     8        //创建公共账号
     9        Account act = new Account("账号sss",10000);
    10        //创建两个线程对同一个账户取款
    11        Thread t1 = new Thread(new P(act));
    12        Thread t2 = new Thread(new P(act));
    13        t1.start();
    14        t2.start();
    15     }
    16 }
    17 //取款线程
    18 class P implements Runnable
    19 {
    20     //账户
    21     Account act;
    22     P(Account act)
    23     {
    24         this.act = act;
    25     }
    26     public void run()
    27     {
    28         act.withdraw(2000);
    29         System.out.println("取款成功,余额为:"+act.getBalance());
    30     }
    31 
    32 }
    33 //账户
    34 class Account
    35 {
    36     private String action;
    37     private double balance;
    38     public Account(){}
    39     public Account(String action,double balance){
    40       this.action = action;
    41       this.balance = balance;
    42     }
    43     public void setAction(String action)
    44     {
    45         this.action = action;
    46     }
    47     
    48     public void setBalance(double balance)
    49     {
    50         this.balance = balance;
    51     }
    52     public String getAction(String action)
    53     {
    54         return action;
    55     }
    56     public double getBalance()
    57     {
    58         return balance;
    59     }
    60     public  synchronized void withdraw(double money)
    61     {
    62         
    63            double after = balance - money;
    64            try{
    65            Thread.sleep(1000);
    66            }catch(Exception e){}
    67            this.setBalance(after);
    68         
    69     }
    70 }
    71 
    72 /*
    73 运行结果:
    74 取款成功,余额为:8000.0
    75 取款成功,余额为:6000.0
    76 请按任意键继续. . .
    77 
    78 */
    View Code

      (另:StirngBuffer  Vector Hashtable 是线程安全的 )

    5.死锁

      例:

     1 /*
     2    死锁
     3 */
     4 class DeadLook
     5 {
     6     public static void main(String[] args) 
     7     {
     8        Object o1 = new Object();    
     9        Object o2 = new Object();
    10        
    11        Thread t1 = new Thread(new T1(o1,o2));
    12        Thread t2 = new Thread(new T2(o1,o2));
    13        t1.start();
    14        t2.start();
    15     }
    16 }
    17 
    18 class T1 implements Runnable
    19 {
    20     Object o1;
    21     Object o2;
    22     T1(Object o1,Object o2)
    23     {
    24         this.o1 = o1;
    25         this.o2 = o2;
    26     }
    27     public void run()
    28     {
    29         synchronized(o1)
    30         {
    31             try{Thread.sleep(1000);}catch(Exception e){}
    32             synchronized(o2)
    33             {
    34                 System.out.println("t1");
    35             }
    36         }
    37     }
    38 }
    39 class T2 implements Runnable
    40 {
    41     Object o1;
    42     Object o2;
    43     T2(Object o1,Object o2)
    44     {
    45         this.o1 = o1;
    46         this.o2 = o2;
    47     }
    48     public void run()
    49     {
    50         synchronized(o2)
    51         {
    52             try{Thread.sleep(1000);}catch(Exception e){}
    53             synchronized(o1)
    54             {
    55                 System.out.println("t2");
    56             }
    57         }
    58     }
    59 }
    View Code

    6.守护线程

      从线程的分类上可以分为:用户线程和守护线程,所有的用户线程结束生命周期,只有一个用户线程存在,那么守护线程就不会结束,Java中的垃圾回收器就

      是一个守护线程,只有应用程序中所有的线程结束,它才会结束。 

      例:

     1 /*
     2    守护线程:
     3    所有的用户线程结束,守护线程才会结束,守护线程是一个无限循环执行的。
     4 */
     5 class  Threadtest08
     6 {
     7     public static void main(String[] args) throws Exception  
     8     {
     9         Thread t1 = new P();
    10         t1.setName("t1");
    11         t1.setDaemon(true);//将用户线程修改为守护线程
    12         t1.start();
    13         //主线程
    14         for(int i = 0;i < 10; i++)
    15         {
    16            System.out.println(Thread.currentThread().getName()+".."+i);
    17            Thread.sleep(1000);
    18         }
    19     }
    20 }
    21 
    22 class P extends Thread
    23 {
    24    public void run()
    25     {
    26        int i = 0;
    27        while(true)
    28         {
    29            i++;
    30            System.out.println(Thread.currentThread().getName()+".."+i);
    31            try{Thread.sleep(1000);}catch(Exception e){}
    32         }
    33     }
    34 }
    35 /*
    36 运行结果:
    37 main..0
    38 t1..1
    39 t1..2
    40 main..1
    41 t1..3
    42 main..2
    43 main..3
    44 t1..4
    45 main..4
    46 t1..5
    47 main..5
    48 t1..6
    49 main..6
    50 t1..7
    51 main..7
    52 t1..8
    53 main..8
    54 t1..9
    55 main..9
    56 t1..10
    57 请按任意键继续. . .
    58 
    59 
    60 */
    View Code

    7.Timer定时器

      作用:每隔一段固定的时间执行一段代码

      例:

     1 /*
     2    定时器
     3 */
     4 import java.text.*;
     5 import java.util.*;
     6 class  Timertest
     7 {
     8     public static void main(String[] args) throws Exception
     9     {
    10         //创建定时器
    11         Timer t = new Timer();
    12         //指定定时任务
    13         t.schedule(new LogTimerTask(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").parse("2017-04-21 11:42:00 000"),10*1000);
    14 
    15     }
    16 }
    17 //指定任务
    18 class LogTimerTask extends TimerTask
    19 {
    20     public void run()
    21     {
    22         System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));
    23     }
    24 }
    View Code

    8.线程池

       参考资料   http://www.importnew.com/19011.html

                        http://lavasoft.blog.51cto.com/62575/27069/

                        https://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247484346&idx=1&sn=f065ebd404771a90988bb097ea4e26dd&chksm=e9c5fa0bdeb2731d12b838372fc8aa97890dd2e3379d1a486df7cf795f8a1538c1ae974a13e7&mpshare=1&scene=23&srcid=1022Iecc2i96j9Drfxgzd274#rd

  • 相关阅读:
    nginx高性能WEB服务器系列之九--nginx运维故障日常解决方案
    nginx高性能WEB服务器系列之一简介及安装
    nginx高性能WEB服务器系列之八--nginx日志分析与切割
    nginx高性能WEB服务器系列之七--nginx反向代理
    nginx高性能WEB服务器系列之六--nginx负载均衡配置+健康检查
    nginx高性能WEB服务器系列之五--实战项目线上nginx多站点配置
    nginx高性能WEB服务器系列之四配置文件详解
    nginx高性能WEB服务器系列之三版本升级
    nginx高性能WEB服务器系列之二命令管理
    阿里云平台微信告警(基于收费平台)
  • 原文地址:https://www.cnblogs.com/xyzyj/p/6159753.html
Copyright © 2011-2022 走看看