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

  • 相关阅读:
    CodeForces 706C Hard problem
    CodeForces 706A Beru-taxi
    CodeForces 706B Interesting drink
    CodeForces 706E Working routine
    CodeForces 706D Vasiliy's Multiset
    CodeForces 703B Mishka and trip
    CodeForces 703C Chris and Road
    POJ 1835 宇航员
    HDU 4907 Task schedule
    HDU 4911 Inversion
  • 原文地址:https://www.cnblogs.com/xyzyj/p/6159753.html
Copyright © 2011-2022 走看看