zoukankan      html  css  js  c++  java
  • 线程和线程池

    一、Thread 类
      构造方法:Thread():创建新的线程
        Thread(String name):创建新的线程并指定改线程名
        Thread(Runnable runnable):创建新的线程并传入指定任务
      常用方法:对象.start():开始线程并执行任务
        run():要执行的任务
        sleep(long millis):暂停多少毫秒后执行
      实现过程:
        1、自定义类使之继承 Thread 类
        2、重写run()方法
        3、创建自定义类对象
        4、调用start()方法

      Demo:

      自定义类

    1 public class MyThread extends Thread {
    2     // run方法是用来描述线程任务的
    3     @Override
    4     public void run() {
    5         for (int i = 0; i < 100; i++) {
    6             System.out.println(getName() + ":" + i);
    7         }
    8     }
    9 }

    开启线程

    1     public static void main(String[] args) {
    2         MyThread mt = new MyThread();
    3         // 开启线程
    4         mt.start();
    5         
    6         for (int i = 0; i < 100; i++) {
    7             System.out.println( Thread.currentThread().getName()+":"+ i);
    8         }
    9     }

    二、Runnable 接口 (创建任务对象)
      好处:创建的任务对象,可以被多次执行,Thread 自定义类执行继承,继承的单一性,但是 Runnable 接口,可以实现多实现,不再单一。
      实现过程:
        1、自定义类使之实现 Runnable 接口
        2、重写Run 方法
        3、创建 自定义类的 对象
        4、创建 Thread 对象 并传入 指定任务对象 (自定义类对象)
        5、调用 Thread 的 start() 方法,使之开始执行任务

      Demo

      自定义类

      

    1 public class MyRunnable implements Runnable {
    2 
    3     @Override
    4     public void run() {
    5         for (int i = 0; i < 100; i++) {
    6             System.out.println(Thread.currentThread().getName() + ":" + i);
    7         }
    8     }
    9 }

    开启线程

     

     1 public static void main(String[] args) {
     2         Thread.currentThread().setName("System");
     3         // 创建线程任务对象
     4         MyRunnable mr = new MyRunnable();
     5                 //创建线程对象,并传入任务
     6         Thread t = new Thread(mr);
     7         t.setName("YHYThread");
     8                 //开启线程
     9         t.start();
    10         for (int i = 0; i < 100; i++) {
    11             System.out.println(Thread.currentThread().getName() + ":" + i);
    12         }
    13     }


    三、使用匿名内部类来实现多线程
    1、使用 Thread
        new Thread(){
          重写run 方法
        }.start();

        

    1 new Thread(new Runnable() {
    2             public void run() {
    3                 Thread.currentThread().setName("YY");
    4                 for (int i = 0; i < 100; i++) {
    5                     System.out.println(Thread.currentThread().getName() + ":" + i);
    6                 }
    7             }
    8         }).start();

        


    2、使用 Runnable
        Runnable r = new Runnable(){
          重写run方法
        };
        Thread t = new Thread(r);
        t.start();

        

     1 public static void main(String[] args) {
     2         Runnable r= new Runnable() {            
     3             @Override
     4             public void run() {
     5                 System.out.println("任务");
     6             }
     7         };
     8         
     9         Thread t= new Thread(r);
    10         t.start();
    11     } 


    四、线程池
      创建线程池对象:
        ExecutorService es = Executors.newFixedThreadPool(int nThreads);//传入需要开始线程的数量。

      使用Runnable 接口实现线程池
          1、创建Runnable的任务对象 并重写 run() 方法。
          2、获取线程池对象
          3、线程池对象.submit(Runnable task);//传入要执行的任务对象
          4、关闭线程池对象 线程池对象.shutdown();

          

     1     public static void main(String[] args) {
     2 //        指定任务对象,可以使用自定义类,实现Runnable接口
     3         Runnable r = new Runnable() {
     4             @Override
     5             public void run() {
     6                 System.out.println("任务");
     7             }
     8         };
     9 
    10 //        获取线程池对象
    11         ExecutorService es = Executors.newFixedThreadPool(2);
    12 //        指定任务
    13         es.submit(r);
    14 //        关闭线程池
    15         es.shutdown();
    16     }

        使用 Callable 接口实现线程池
          1、创建 Callable 的任务对象,并重写 call() 方法。
          2、创建线程池对象
          3、线程池对象.submit(Callable c);//传入任务对象 (Callable 对象),假如有参数,使用Future<返回值类型> 接收
          4、获取返回值 Future<返回值类型>对象.get() 获取 call() 方法的返回值
          5、关闭线程池对象

          

     1     public static void main(String[] args) throws InterruptedException, ExecutionException {
     2 //        指定任务对象,并指定返回值,可以使用自定义类,实现Callable接口
     3         Callable<String> c = new Callable<String>() {
     4             @Override
     5             public String call() throws Exception {
     6 
     7                 return "aaa";
     8             }
     9         };
    10 
    11 //        获取线程池对象
    12         ExecutorService es = Executors.newFixedThreadPool(2);
    13 //        传入指定任务并使用 Future<V> 接收返回值
    14         Future<String> submit = es.submit(c);
    15 //        Future<V>对象 的 get() 方法接收返回值
    16         String str = submit.get();
    17         System.out.println(str);
    18 //        关闭线程池
    19         es.shutdown();
    20     }

    Callable 比Runable 的好处是:可以抛异常,可以有返回值

    五、线程安全
      当线程任务共享一个数据源,并对这个数据进行操作的时候,有可能出现错误数据,这个时候就要用同步代码块,或者同步方法。
        1、定义一个同步代码块

         在 线程任务 方法外 定义任意对象 例如 

          

     1 package com.oracle.demo04;
     2 
     3 
     4 public class Tickets implements Runnable {
     5 
     6 //    所有线程共享数据放到成员位置
     7     private int ticks = 100;
     8 
     9 //    创建枷锁
    10     Object lock = new Object();
    11     
    12     @Override
    13     public void run() {
    14         while (true) {
    15             try {
    16                 Thread.sleep(500);
    17             } catch (InterruptedException e) {
    18                 // TODO Auto-generated catch block
    19                 e.printStackTrace();
    20             }
    21             synchronized (lock) {
    22                 if (ticks > 0) {
    23                     System.out.println(Thread.currentThread().getName() + "窗口卖了第:" + ticks-- + "张票");
    24                 }
    25             }
    26         }
    27 
    28     }
    29 
    30 }

      将有肯能影响数据的地方用 synchronized(object){ 问题代码 } 

          


       2、定义一个同步方法 用 synchronized 修饰的方法

        

     1 package com.oracle.demo04;
     2 
     3 public class Tickets2 implements Runnable {
     4 //    所有线程共享数据放到成员位置
     5     private int ticks = 100;
     6 
     7 //    创建枷锁
     8     Object lock = new Object();
     9 
    10     @Override
    11     public void run() {
    12         while (true) {
    13             try {
    14                 Thread.sleep(500);
    15             } catch (InterruptedException e) {
    16                 // TODO Auto-generated catch block
    17                 e.printStackTrace();
    18             }
    19             method();
    20         }
    21     }
    22 
    23     private synchronized void method() {
    24 
    25         if (ticks > 0) {
    26             System.out.println(Thread.currentThread().getName() + "窗口卖了第:" + ticks-- + "张票");
    27         }
    28     }
    29 }

        然后在 线程任务中调用该方法。

       

        3、使用 lock 类。控制 同步代码块  

          

     1 package com.oracle.demo04;
     2 
     3 import java.util.concurrent.locks.Lock;
     4 import java.util.concurrent.locks.ReentrantLock;
     5 
     6 public class Tickets3 implements Runnable {
     7 
     8 //    所有线程共享数据放到成员位置
     9     private int ticks = 100;
    10 
    11     private Lock lock = new ReentrantLock();
    12 
    13     @Override
    14     public void run() {
    15         while (true) {
    16 
    17             lock.lock();
    18             try {
    19                 Thread.sleep(500);
    20             } catch (InterruptedException e) {
    21                 // TODO Auto-generated catch block
    22                 e.printStackTrace();
    23             }
    24 //            调用 lock 方法 获取锁
    25             if (ticks > 0) {
    26                 System.out.println(Thread.currentThread().getName() + "窗口卖了第:" + ticks-- + "张票");
    27             }
    28             if(ticks > 3) {
    29                 System.out.println(Thread.currentThread().getName() + "窗口卖了第:" + ticks-- + "张票");
    30             }
    31 //            调用 unlock 方法 释放锁
    32             lock.unlock();
    33         }
    34     }
    35 
    36 }
  • 相关阅读:
    C# 开发规范
    C# 调用webserver 出现:未能从程序集“jgd3jufm, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”中加载类型
    C# 组装XML传给webserver+XML 返回获取多个xml,根据多个XML 返回dataset类型
    linux下搭建git服务器
    Linux整合Apache和SVN
    JAVA通过Gearman实现MySQL到Redis的数据同步(异步复制)
    比尔盖茨的十句忠告
    Spring核心接口之InitializingBean
    mongodb安装和配置
    redis主从配置
  • 原文地址:https://www.cnblogs.com/yanghaoyu0624/p/11737068.html
Copyright © 2011-2022 走看看