• Java多线程记录(包含案例)


    线程是程序的执行单元,执行路径。是程序使用CPU的最基本单位

    多线程 -- 程序有多条执行路径,提高应用进程的使用率

    进程中线程越多,抢到CPU执行权概率越高。线程的执行有随机性

    Java程序的运行原理:

    由Java命令启动JVM,JVM启动就相当于启动了一个进程,接着由该程序创建了一个主线程去调用main方法

    JVM的启动是多线程的,因为垃圾回收线程也要启动,否则容易出现内存溢出。(GC线程和主线程)

    Java多线程程序:

    方法1:继承Thread类,并重写run()方法,创建对象,执行对象。

      run()方法: Thread类中的run()用来包含那些被线程执行的代码(封装被线程执行的代码)(不单独调用run方法(直接调用是普通方法),调用start())

      start()方法:首先启动了线程,然后再由JVM去调用该线程的run()方法

    方法2:实现runnable接口

      A:自定义类实现runnable

      B:重写run()方法

      C:创建MyRunnable类的对象 

      D:创建Thread类的对象,把C步骤的对象作为构造参数传递

    解决了java单继承的局限性,适合多个相同程序代码去处理同一个资源的情况,把线程相同的代码,数据有效分离

    一些内建方法:

    public final String getName()   //获取线程名称
    public final String setName():    //设置线程名称
    public static Thread currentThread():    //返回当前正在执行的线程对象

    抢占式调度模型(Java):优先让优先级高的线程使用CPU

    public final int getPriority():   //返回线程对象的优先级
    public final void setPriority(): //设置线程优先级

    优先级范围1-10,默认为5,最低为1,最高为5

    线程控制:

    public static void sleep(long millis)    //线程休眠
    public final void join():   //线程加入   (等待线程终止)
    public static void yield():  //线程礼让 暂停当前正在执行的线程对象,并执行其他线程
    //让多个线程的执行更加和谐,但不能保证
    public final void setDaemon(boolean on): //设置守护线程
    //当正在运行的线程都是守护线程时,JVM退出,该方法必须在启动线程前调用
    public void interrupt(): //中断线程,把线程的状态终止,并抛出一个InterruptException

    线程的生命周期:(图解)

    线程同步:synchronized关键字 

    将多条语句操作的共享数据代码包成一个整体,让某个线程在执行的时候别人不执行

    前提:多个线程;  注意:多个线程使用同一个锁对象

    优点:解决了多线程的安全问题

    缺点:当线程相当时,因为每个线程都会去判断同步上的锁,很耗费资源,无形中降低了程序的运行效率,容易产生死锁

    使用同步代码块或者同步方法

    死锁:

    死锁代码举例:

    1 public class MyLock {
    2     // 创建两把锁对象
    3     public static final Object objA = new Object();
    4     public static final Object objB = new Object();
    5 }
     1 public class DeadLock extends Thread {
     2 
     3     private boolean flag;
     4 
     5     public DeadLock(boolean flag) {
     6         this.flag = flag;
     7     }
     8 
     9     @Override
    10     public void run() {
    11         if (flag) {
    12             synchronized (MyLock.objA) {
    13                 System.out.println("if objA");
    14                 synchronized (MyLock.objB) {
    15                     System.out.println("if objB");
    16                 }
    17             }
    18         } else {
    19             synchronized (MyLock.objB) {
    20                 System.out.println("else objB");
    21                 synchronized (MyLock.objA) {
    22                     System.out.println("else objA");
    23                 }
    24             }
    25         }
    26     }
    27 }
    1 public class DieLockDemo {
    2     public static void main(String[] args) {
    3         DeadLock dl1 = new DeadLock(true);
    4         DeadLock dl2 = new DeadLock(false);
    5 
    6         dl1.start();
    7         dl2.start();
    8     }
    9 }

    等待唤醒机制:

    Object类提供三个方法:

    wait() :等待

    notify():唤醒单个线程

    notifyAll():唤醒所有线程

    为什么不在Thread类中: 因为这些方法必须通过锁对象调用,而锁对象可以是任意锁对象,所以定义在object类中

    Semaphore信号量:

    信号量(Semaphore),又被称为信号灯,在多线程环境下用于协调各个线程, 以保证它们能够正确、合理的使用公共资源。信号量维护了一个许可集,我们在初始化Semaphore时需要为这个许可集传入一个数量值,该数量值代表同一时间能访问共享资源的线程数量。

    线程可以通过acquire()方法获取到一个许可,然后对共享资源进行操作,注意如果许可集已分配完了,那么线程将进入等待状态,直到其他线程释放许可才有机会再获取许可,线程释放一个许可通过release()方法完成,"许可"将被归还给Semaphore。

    多线程案例:

    电影院卖票:电影院一共有100张票,有三个窗口卖票,模拟电影院售票:

    使用同步代码块:

    public class SellTicket implements Runnable {
        // 定义100张票
        private int tickets = 100;
        //创建锁对象
        private Object obj = new Object();
        
        @Override
        public void run() {
            while (true) {
                synchronized (obj) {
                    if (tickets > 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()
                                + "正在出售第" + (tickets--) + "张票");
                    }
                }
            }
        }
    }
    public class SellTicketDemo {
        public static void main(String[] args) {
            // 创建资源对象
            SellTicket st = new SellTicket();
    
            // 创建三个线程对象
            Thread t1 = new Thread(st, "窗口1");
            Thread t2 = new Thread(st, "窗口2");
            Thread t3 = new Thread(st, "窗口3");
    
            // 启动线程
            t1.start();
            t2.start();
            t3.start();
        }
    }

    使用同步方法:

     1 package lab2;
     2 
     3 public class SellTicket implements Runnable {
     4 
     5     // 定义100张票
     6     private static int tickets = 100;
     7 
     8     @Override
     9     public void run() {
    10         while (true) {
    11             sellTicket();
    12         }
    13     }
    14     
    15      private synchronized void sellTicket() {
    16             if (tickets > 0) {
    17             try {
    18                     Thread.sleep(100);
    19             } catch (InterruptedException e) {
    20                     e.printStackTrace();
    21             }
    22             System.out.println(Thread.currentThread().getName()
    23                         + "正在出售第" + (tickets--) + "张票 ");
    24             }
    25     }
    26 }

    使用锁方法:

     1 import java.util.concurrent.locks.Lock;
     2 import java.util.concurrent.locks.ReentrantLock;
     3 
     4 public class SellTicket implements Runnable {
     5 
     6     // 定义票
     7     private int tickets = 100;
     8 
     9     // 定义锁对象
    10     private Lock lock = new ReentrantLock();
    11 
    12     @Override
    13     public void run() {
    14         while (true) {
    15             try {
    16                 // 加锁
    17                 lock.lock();
    18                 if (tickets > 0) {
    19                     try {
    20                         Thread.sleep(100);
    21                     } catch (InterruptedException e) {
    22                         e.printStackTrace();
    23                     }
    24                     System.out.println(Thread.currentThread().getName()
    25                             + "正在出售第" + (tickets--) + "张票");
    26                 }
    27             } finally {
    28                 // 释放锁
    29                 lock.unlock();
    30             }
    31         }
    32     }
    33 
    34 }

    Ornamental Garden Problem:(使用Bakery class) 花园有两个旋转门,可进可出,监控花园内的人数

    volatile关键字: Specifying a variable as volatile instructs the compiler to load and store the value of the variable at each use.   另外更多说明可以参考:https://www.cnblogs.com/daxin/p/3364014.html

    Bakery Algorithm面包店算法

    Bakery.java

     1 package lab2;
     2 
     3 public class Bakery {
     4     public int nThreads;
     5     
     6     private volatile int[] ticket;
     7     private volatile boolean[] choosing;
     8     
     9     Bakery(int nTh) {
    10         nThreads = nTh;
    11         ticket = new int[nThreads];
    12         choosing = new boolean[nThreads];
    13         
    14         for (int i = 0; i < nThreads; i++) {
    15             System.out.println(i + ticket[1]);
    16             ticket[i] = 0;
    17             choosing[i] = false;
    18         }
    19     }
    20     
    21     private int getNextNumber() {
    22         int largest = 0;
    23         for (int i = 0; i < nThreads; i++) {
    24             if (ticket[i] > largest)
    25                 largest = ticket[i];
    26         }
    27         return largest + 1;
    28     }
    29     
    30     private boolean isFavouredThread(int i, int j) {
    31         if ((ticket[i] == 0) || (ticket[i] > ticket[j]))
    32             return false;
    33         else {
    34             if (ticket[i] < ticket[j])
    35                 return true;
    36             else
    37                 return (i < j);
    38         }
    39     }
    40 
    41     void wantToEnterCS(int threadID) {
    42         choosing[threadID] = true;
    43         ticket[threadID] = getNextNumber();
    44         choosing[threadID] = false;
    45         
    46         for (int otherThread = 0; otherThread < nThreads; otherThread++) {
    47             while(choosing[otherThread]) {
    48                 // busy-wait
    49             }
    50             // Break any ties between threads
    51             while (isFavouredThread(otherThread,threadID)) {
    52                 // busy-wait
    53             }
    54         }
    55     }
    56 
    57     void exitCS(int threadID) {
    58         // Leave critical section
    59         ticket[threadID] = 0;
    60     }
    61 }

    Couter.java

     1 package lab2;
     2 
     3 public class Counter {
     4     volatile int value = 0;
     5 
     6     Counter() {
     7         System.out.println("TOTAL: " + value);
     8     }
     9 
    10     boolean increment() {
    11         int temp = value;   //read[v]
    12         Simulate.HWinterrupt();
    13         value = temp + 1;       //write[v+1]
    14         System.out.println("TOTAL: " + value);
    15             return true;
    16     }
    17 
    18     boolean decrement() {
    19         int temp = value;   //read[v]
    20         Simulate.HWinterrupt();
    21             if (temp == 0) return false;
    22         Simulate.HWinterrupt();
    23         value = temp - 1;       //write[v+1]
    24         System.out.println("TOTAL: " + value);
    25             return true;
    26     }
    27 }
    28 
    29 class Simulate {
    30     public static void HWinterrupt() {
    31         if (Math.random() < 0.5)
    32            try{
    33                Thread.sleep(200);
    34            } catch(InterruptedException ie) {};
    35     }
    36 }

    Turnstile.java

     1 package lab2;
     2 
     3 /* Notes:
     4  * No modifications need be made to the bakery class.  Instead, the turnstile
     5  * class and counter classes are adjusted to allow for "exit" turnstiles as well
     6  * as entrance turnstiles.  This solution incorporates a system to prevent the
     7  * number of people in the gardens from being negative, so the sleep call in
     8  * this class can be commented out.  Study the code in the Counter and Turnstile
     9  * classes to see how how this works.
    10  * */
    11 
    12 public class Gardens {
    13      static Turnstile west;
    14      static Turnstile east;
    15      static Turnstile westExit;
    16      static Turnstile eastExit;
    17      static Counter people;
    18      static Bakery bakery;
    19      
    20     public static void main(String[] args) {
    21         people = new Counter();
    22         bakery = new Bakery(4);
    23          
    24          west = new Turnstile(0, true, people, bakery);
    25          east = new Turnstile(1, true, people, bakery);
    26 
    27          westExit = new Turnstile(2, false, people, bakery);
    28          eastExit = new Turnstile(3, false, people, bakery);
    29          
    30          west.start();
    31          east.start();
    32 
    33         /* 
    34         try {
    35             Thread.sleep(5000);
    36         } catch (InterruptedException e) {
    37         }
    38         */
    39 
    40         westExit.start();
    41         eastExit.start();
    42     }
    43 }

    Garden.java

     1 package lab2;
     2 
     3 public class Gardens {
     4      static Turnstile west;
     5      static Turnstile east;
     6      static Turnstile westExit;
     7      static Turnstile eastExit;
     8      static Counter people;
     9      static Bakery bakery;
    10      
    11     public static void main(String[] args) {
    12         people = new Counter();
    13         bakery = new Bakery(4);
    14          
    15          west = new Turnstile(0, true, people, bakery);
    16          east = new Turnstile(1, true, people, bakery);
    17 
    18          westExit = new Turnstile(2, false, people, bakery);
    19          eastExit = new Turnstile(3, false, people, bakery);
    20          
    21          west.start();
    22          east.start();
    23 
    24         /* 
    25         try {
    26             Thread.sleep(5000);
    27         } catch (InterruptedException e) {
    28         }
    29         */
    30 
    31         westExit.start();
    32         eastExit.start();
    33     }
    34 }

    生产者消费者,操作列表:

    Buffer.java

     1 import java.util.LinkedList;
     2 import java.util.NoSuchElementException;
     3 
     4 class Buffer {
     5     LinkedList<Integer> queue = new LinkedList<Integer>();
     6     
     7     public synchronized void write(int i) {
     8         queue.add(i);
     9     }
    10 
    11     public synchronized int read() {
    12         try {
    13             return queue.removeFirst();
    14         } catch(NoSuchElementException e) {
    15             // the buffer is empty!?
    16             return -1;
    17         }
    18     }
    19 }

    Producer.java

     1 class Producer implements Runnable {
     2     Buffer buffer;
     3 
     4     public Producer(Buffer b) {
     5         buffer = b;
     6     }
     7 
     8     public void run() {
     9         for(int i = 0; i < 20; i++) {
    10             buffer.write(i);
    11             System.out.println("Thread " + Thread.currentThread().getId() +
    12                 " writes " + i);
    13         }
    14     }
    15 }

    Consumer.java

     1 class Consumer implements Runnable {
     2     Buffer buffer;
     3 
     4     public Consumer(Buffer b) {
     5         buffer = b;
     6     }
     7 
     8     public void run() {
     9         for(int i = 0; i < 10; i++) {
    10             try {
    11                 Thread.sleep(10);
    12             } catch (InterruptedException e) {
    13             }
    14             int x = buffer.read();
    15             System.err.println("Thread " + Thread.currentThread().getId() +
    16                 " reads " + x);
    17         }
    18     }
    19 }

    InfBuffer.java

     1 public class InfBuffer {
     2     public static void main(String args[]) {
     3         Buffer b = new Buffer();
     4         Consumer c1 = new Consumer(b);
     5         Consumer c2 = new Consumer(b);
     6         Producer p = new Producer(b);
     7         (new Thread(c1)).start();
     8         (new Thread(c2)).start();
     9         (new Thread(p)).start();
    10     }
    11 }

    生产者消费者,修改学生姓名和年龄并获取:(只能一打一大片,无法实现生产者生产后等待消费者消费后再产生)

    1 public class Student {
    2     String name;
    3     int age;
    4 }
     1 public class SetThread implements Runnable {
     2 
     3     private Student s;
     4     private int x = 0;
     5 
     6     public SetThread(Student s) {
     7         this.s = s;
     8     }
     9 
    10     @Override
    11     public void run() {
    12         while (true) {
    13             synchronized (s) {
    14                 if (x % 2 == 0) {
    15                     s.name = "Student1";
    16                     s.age = 27;
    17                 } else {
    18                     s.name = "Student2"; 
    19                     s.age = 30;
    20                 }
    21                 x++;
    22             }
    23         }
    24     }
    25 }
     1 public class GetThread implements Runnable {
     2     private Student s;
     3 
     4     public GetThread(Student s) {
     5         this.s = s;
     6     }
     7 
     8     @Override
     9     public void run() {
    10         while (true) {
    11             synchronized (s) {
    12                 System.out.println(s.name + "---" + s.age);
    13             }
    14         }
    15     }
    16 }
     1 public class StudentDemo {
     2     public static void main(String[] args) {
     3         //创建资源
     4         Student s = new Student();
     5         
     6         //设置和获取的类
     7         SetThread st = new SetThread(s);
     8         GetThread gt = new GetThread(s);
     9 
    10         //线程类
    11         Thread t1 = new Thread(st);
    12         Thread t2 = new Thread(gt);
    13 
    14         //启动线程
    15         t1.start();
    16         t2.start();
    17     }
    18 }

    生产者消费者,修改学生姓名和年龄并获取:(使用等待唤醒机制改进)

    1 public class Student {
    2     String name;
    3     int age;
    4     boolean flag;  //添加一个标记,默认为false,表示生产者是否生成值
    5 }
     1 public class SetThread implements Runnable {
     2 
     3     private Student s;
     4     private int x = 0;
     5 
     6     public SetThread(Student s) {
     7         this.s = s;
     8     }
     9 
    10     @Override
    11     public void run() {
    12         while (true) {
    13             synchronized (s) {
    14                 //判断有没有
    15                 if(s.flag) {
    16                     try {
    17                         s.wait();
    18                     } catch (InterruptedException e) {
    19                         e.printStackTrace();
    20                     }
    21                 } 
    22                 
    23                 if (x % 2 == 0) {
    24                     s.name = "Student1";
    25                     s.age = 27;
    26                 } else {
    27                     s.name = "Student2"; 
    28                     s.age = 30;
    29                 }
    30                 x++;
    31                 
    32                 //修改标记
    33                 s.flag = true;
    34                 //唤醒线程
    35                 s.notify();
    36             }
    37         }
    38     }
    49 }
     1 public class GetThread implements Runnable {
     2     private Student s;
     3 
     4     public GetThread(Student s) {
     5         this.s = s;
     6     }
     7 
     8     @Override
     9     public void run() {
    10         while (true) {
    11             synchronized (s) {
    12                 if (!s.flag) {
    13                     try {
    14                         s.wait();
    15                     } catch (InterruptedException e) {
    16                         e.printStackTrace();
    17                     }
    18                 }
    19                 System.out.println(s.name + "---" + s.age);
    20                 
    21                 //修改标记
    22                 s.flag = false;
    23                 //唤醒线程
    24                 s.notify();
    25                 
    26             }
    27         }
    28     }
    29 }
    public class StudentDemo {    //同上
        public static void main(String[] args) {
            //创建资源
            Student s = new Student();
            
            //设置和获取的类
            SetThread st = new SetThread(s);
            GetThread gt = new GetThread(s);
    
            //线程类
            Thread t1 = new Thread(st);
            Thread t2 = new Thread(gt);
    
            //启动线程
            t1.start();
            t2.start();
        }
    }

    厕所排队(使用信号量)

     1 import java.util.Random;
     2 import java.util.concurrent.Semaphore;
     3 
     4 class Wc extends Thread {
     5     private String name;
     6     private Semaphore wc;
     7     
     8     public Wc(String name, Semaphore wc) {
     9         this.name = name;
    10         this.wc = wc;
    11     }
    12     
    13     @Override
    14     public void run() {
    15         int availablePermit = wc.availablePermits();
    16         if (availablePermit > 0) {
    17             System.out.println(name+",好开心啊,我终于有坑了");
    18         }else {
    19             System.out.println(name+"怎么没有坑了。。。");
    20         }
    21         
    22         try {
    23             wc.acquire();
    24             System.out.println(name+",好开心啊,我终于抢到了!");
    25             Thread.sleep(new Random().nextInt(1000));
    26             System.out.println(name+",好爽啊,终于上完了!");
    27             wc.release();
    28         } catch (InterruptedException e) {
    29 
    30         }
    31     }
    32 }
    33 
    34 public class Demo {
    35     public static void main(String[] args) {
    36         Semaphore semaphore = new Semaphore(3);
    37         
    38         for (int i = 0; i < 10; i++) {
    39             Wc wc = new Wc("第"+i+"个人", semaphore);
    40             wc.start();
    41         }
    42     }
    43 }

    The Sleeping Barber (生产者消费者,信号量)

     1 import java.util.concurrent.Semaphore;
     2 
     3 public class Barber implements Runnable{
     4 
     5     Semaphore customerWaiting, seats, barberSleeping;
     6     
     7     Barber(Semaphore customerWaiting, Semaphore seats, Semaphore barberSleeping) {
     8         this.customerWaiting = customerWaiting;
     9         this.seats = seats;
    10         this.barberSleeping = barberSleeping;
    11     }
    12     
    13     public void run() {
    14         
    15         while (true){
    16             
    17             // Get a customer, sleep otherwise
    18             try {
    19                 customerWaiting.acquire();
    20             } catch (InterruptedException e) {}
    21 
    22             // Cut the hair of the customer    
    23             System.out.println("Cutting Hair");
    24             barberSleeping.release();            
    25             
    26         }
    27     }
    28 }
     1 import java.util.concurrent.Semaphore;
     2 
     3 public class Customer implements Runnable{
     4 
     5     Semaphore customerWaiting, seats, barberSleeping;
     6 
     7     boolean cut = false;
     8     Customer(Semaphore customerWaiting, Semaphore seats, Semaphore barberSleeping) {
     9         this.customerWaiting = customerWaiting;
    10         this.seats = seats;
    11         this.barberSleeping = barberSleeping;
    12 
    13     }
    14     
    15     public void run() {
    16         while (!cut) {
    17             
    18             // A random delay
    19             // Don't want all the threads trying at once!
    20             try {
    21                 Thread.sleep((long)(Math.random()*100));
    22             } catch (InterruptedException e1) {}
    23             
    24             // Try to get a seat in the waiting room
    25             try {
    26                 seats.acquire();
    27             } catch (InterruptedException e) {}
    28             System.out.println(seats.availablePermits());
    29 
    30                 System.out.println(Thread.currentThread().getName()+" is sitting down");
    31                 // Try and wake barber
    32                 customerWaiting.release();
    33 
    34                 
    35                 // Get hair cut
    36                 try {
    37                     barberSleeping.acquire();
    38                 } catch (InterruptedException e) {}
    39                 cut = true;
    40                 seats.release();
    41             
    42         }
    43         System.out.println(Thread.currentThread().getName()+" has had hair cut");        
    44     }
    45 }
     1 import java.util.concurrent.Semaphore;
     2 
     3 public class Runner {
     4 
     5     public static void main(String[] args) {
     6         
     7         Semaphore barberSleeping = new Semaphore(1);
     8         Semaphore customerWaiting = new Semaphore(1);
     9         try {
    10             customerWaiting.acquire();
    11             barberSleeping.acquire();
    12         } catch (InterruptedException e) {
    13         }
    14         
    15         Semaphore seats = new Semaphore(3);
    16         
    17         Barber bar = new Barber(customerWaiting,seats,barberSleeping);
    18         Thread bThread = new Thread(bar);
    19         bThread.start();
    20         
    21         int nCust = 30;
    22         Customer customers[] = new Customer[nCust];
    23         Thread cThread[] = new Thread[nCust];
    24         
    25         for (int i=0;i<nCust;i++) {
    26              customers[i] = new Customer(customerWaiting,seats,barberSleeping);
    27              cThread[i] = new Thread(customers[i]);
    28              cThread[i].start();
    29         }
    30     }
    31 }

    线程池:

    程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互,而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池

    线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。

     1 public class ExecutorsDemo {
     2     public static void main(String[] args) {
     3         // 创建一个线程池对象,控制要创建几个线程对象。
     4         // public static ExecutorService newFixedThreadPool(int nThreads)
     5         ExecutorService pool = Executors.newFixedThreadPool(2);        //直接通过类名调用
     6 
     7         // 可以执行Runnable对象或者Callable对象代表的线程
     8         pool.submit(new MyRunnable());
     9         pool.submit(new MyRunnable());
    10 
    11         //结束线程池
    12         pool.shutdown();
    13     }
    14 }

    使用Callable方法

    public class MyCallable implements Callable {
    
        @Override
        public Object call() throws Exception {
            for (int x = 0; x < 100; x++) {
                System.out.println(Thread.currentThread().getName() + ":" + x);
            }
            return null;
        }
    
    }
    public class CallableDemo {
        public static void main(String[] args) {
            //创建线程池对象
            ExecutorService pool = Executors.newFixedThreadPool(2);
            
            //可以执行Runnable对象或者Callable对象代表的线程
            pool.submit(new MyCallable());
            pool.submit(new MyCallable());
            
            //结束
            pool.shutdown();
        }
    }

    Callable带返回值:

     1 public class CallableDemo {
     2     public static void main(String[] args) throws InterruptedException, ExecutionException {
     3         // 创建线程池对象
     4         ExecutorService pool = Executors.newFixedThreadPool(2);
     5 
     6         // 可以执行Runnable对象或者Callable对象代表的线程
     7         Future<Integer> f1 = pool.submit(new MyCallable(100));
     8         Future<Integer> f2 = pool.submit(new MyCallable(200));
     9 
    10         // V get()
    11         Integer i1 = f1.get();
    12         Integer i2 = f2.get();
    13 
    14         System.out.println(i1);
    15         System.out.println(i2);
    16 
    17         // 结束
    18         pool.shutdown();
    19     }
    20 }
     1 public class MyCallable implements Callable<Integer> {
     2 
     3     private int number;
     4 
     5     public MyCallable(int number) {
     6         this.number = number;
     7     }
     8 
     9     @Override
    10     public Integer call() throws Exception {
    11         int sum = 0;
    12         for (int x = 1; x <= number; x++) {
    13             sum += x;
    14         }
    15         return sum;
    16     }
    17 
    18 }

    匿名内部类实现多线程:

     1 public class ThreadDemo {
     2     public static void main(String[] args) {
     3         // 继承Thread类来实现多线程
     4         new Thread() {
     5             public void run() {
     6                 for (int x = 0; x < 100; x++) {
     7                     System.out.println(Thread.currentThread().getName() + ":"
     8                             + x);
     9                 }
    10             }
    11         }.start();
    12 
    13         // 实现Runnable接口来实现多线程
    14         new Thread(new Runnable() {
    15             @Override
    16             public void run() {
    17                 for (int x = 0; x < 100; x++) {
    18                     System.out.println(Thread.currentThread().getName() + ":"
    19                             + x);
    20                 }
    21             }
    22         }) {
    23         }.start();
    24 
    25         // 更有难度的
    26         new Thread(new Runnable() {
    27             @Override
    28             public void run() {
    29                 for (int x = 0; x < 100; x++) {
    30                     System.out.println("hello" + ":" + x);
    31                 }
    32             }
    33         }) {
    34             public void run() {        //走的是这边的run方法
    35                 for (int x = 0; x < 100; x++) {
    36                     System.out.println("world" + ":" + x);
    37                 }
    38             }
    39         }.start();
    40     }
    41 }
  • 相关阅读:
    27. 移除元素-数组-简单
    26. 删除排序数组中的重复项-数组-简单
    25. K 个一组翻转链表-链表-困难
    24. 两两交换链表中的节点-链表、递归-中等难度
    23. 合并K个排序链表-链表-困难
    21. 合并两个有序链表-链表-简单
    20. 有效的括号-栈-简单
    19. 删除链表的倒数第N个节点-链表-中等难度
    17. 电话号码的字母组合-dfs-中等难度
    16. 最接近的三数之和-dfs-中等难度
  • 原文地址:https://www.cnblogs.com/AICROC/p/12813570.html
Copyright © 2020-2023  润新知