【JAVA】多线程编程实现实例(全面实现)

您所在的位置:网站首页 java线程太多 【JAVA】多线程编程实现实例(全面实现)

【JAVA】多线程编程实现实例(全面实现)

2023-08-26 06:05| 来源: 网络整理| 查看: 265

首先,我们我们要进行多线程编程,最少线程怎么创建时最基本的知识。

创建线程由四种方式

1.继承Thread类创建线程(重写run方法,用start()开启线程)

2.实现Runable接口创建线程(重写run方法,也是start来开启线程)

3.使用Callable和Future创建线程(用Lambda表达式创建Callable对象,用Future来包装该对象,可以有返回值)

4.使用线程池(Executore框架)

我们创建一个场景,有三个站台再卖20张票,再一个站台卖某张票的时候,其他站台不能同时卖这张票。

线程创建方式知道了,那么多线程编程还有一个很重要的就是怎么同步

1.synchronized关键字

2.Atomic实现原子性

3.lock锁

1、继承Thread类创建线程 synchronized关键字 import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; public class TestThread2 { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); Station1 st1 = new Station1("station 1",countDownLatch); Station1 st2 = new Station1("station 2",countDownLatch); Station1 st3 = new Station1("station 3",countDownLatch); long time = System.currentTimeMillis(); st1.start(); st2.start(); st3.start(); countDownLatch.await(); System.out.println((System.currentTimeMillis() - time)); } } class Station1 extends Thread { static CountDownLatch countDownLatch; Object lock = "lock"; static int tick = 20;//保持多个站台线程间票量一直要用static public Station1(String name, CountDownLatch countDownLatch){ super(name);//给线程命名 this.countDownLatch = countDownLatch; } @Override public void run(){ while(tick > 0){ synchronized (lock){ if(tick > 0){ System.out.println(getName() + " 卖出了第" + tick + "张票" ); tick--; //System.out.println("剩下 " + tick + " 张票" ); }else { System.out.println("票卖完了"); } try { sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } } countDownLatch.countDown(); } }

输出结果,可以看到卖20张票因为synchronized锁的缘故,时间非常慢,要用20多秒,synchronized的效率问题已经很直观了。

Atomic实现原子性 import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; public class TestThread { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); Station st1 = new Station("station 1",countDownLatch); Station st2 = new Station("station 2",countDownLatch); Station st3 = new Station("station 3",countDownLatch); long time = System.currentTimeMillis(); st1.start(); st2.start(); st3.start(); countDownLatch.await(); System.out.println((System.currentTimeMillis() - time)); } } class Station extends Thread { static CountDownLatch countDownLatch; static AtomicInteger tick = new AtomicInteger(20);//保持多个站台线程间票量一直要用static public Station(String name, CountDownLatch countDownLatch){ super(name);//给线程命名 this.countDownLatch = countDownLatch; } @Override public void run(){ while(tick.get() > 0){ if(tick.get() > 0){ int i = tick.getAndDecrement(); System.out.println(getName() + " 卖出了第" + i + "张票" ); //System.out.println("剩下 " + tick + " 张票" ); }else { System.out.println("票卖完了"); } try { sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } countDownLatch.countDown(); } }

lock锁 import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class TestThread3 { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); Station st1 = new Station("station 1",countDownLatch); Station st2 = new Station("station 2",countDownLatch); Station st3 = new Station("station 3",countDownLatch); long time = System.currentTimeMillis(); st1.start(); st2.start(); st3.start(); countDownLatch.await(); System.out.println((System.currentTimeMillis() - time)); } } class Station3 extends Thread { static CountDownLatch countDownLatch; static int tick = 20;//保持多个站台线程间票量一直要用static private Lock lock = new ReentrantLock(); public Station3(String name, CountDownLatch countDownLatch){ super(name);//给线程命名 this.countDownLatch = countDownLatch; } @Override public void run(){ while(tick > 0){ lock.lock(); if(tick > 0){ System.out.println(getName() + " 卖出了第" + tick + "张票" ); tick --; //System.out.println("剩下 " + tick + " 张票" ); }else { System.out.println("票卖完了"); } lock.unlock(); try { sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } countDownLatch.countDown(); } }

结果

可以看到,Atomic和lock的时间差不多,因为底层实现都是CAS,所以比synchronized要快很多,AtomicInteger用起来比较方便,所以后面的例子值用AtomicInteger来实现。

2、实现Runable接口创建线程

可以看到,第一个不同是实现了Runnable接口的Station类并不是一个Thread对象,所以在start的时候需要new一个Thread对象然后执行,这一步,没有Thread方便。

第二个是给线程命名需要自己手动写,所以也麻烦了不少。

Runnable接口的好处就是实现了Runnable接口还可以实现别的接口,但是继承了Thread类就只能继承这一个类了,所以可以根据情况进行选择。

import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import static java.lang.Thread.sleep; public class TestThread { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); Station st1 = new Station("station 1",countDownLatch); Station st2 = new Station("station 2",countDownLatch); Station st3 = new Station("station 3",countDownLatch); long time = System.currentTimeMillis(); new Thread(st1).start(); new Thread(st2).start(); new Thread(st3).start(); countDownLatch.await(); System.out.println((System.currentTimeMillis() - time)); } } class Station implements Runnable { static CountDownLatch countDownLatch; static AtomicInteger tick = new AtomicInteger(20);//保持多个站台线程间票量一直要用static String name; public Station(String name, CountDownLatch countDownLatch){ this.name = name;//给线程命名 this.countDownLatch = countDownLatch; } public String getName() { return name; } @Override public void run(){ while(tick.get() > 0){ if(tick.get() > 0){ int i = tick.getAndDecrement(); System.out.println(getName() + " 卖出了第" + i + "张票" ); //System.out.println("剩下 " + tick + " 张票" ); }else { System.out.println("票卖完了"); } try { sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } countDownLatch.countDown(); } }

3、使用Callable和Future创建线程

在JDK8出来后,使用Callable和Future创建线程可以用Lambda表达式来创建线程

import java.awt.*; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.FutureTask; import java.util.concurrent.atomic.AtomicInteger; import static java.lang.Thread.sleep; public class TestThread { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); long time = System.currentTimeMillis(); AtomicInteger tick = new AtomicInteger(20); for(int i = 0; i < 3 ;++ i){ FutureTask station = new FutureTask((Callable)()->{ while(tick.get() > 0){ if(tick.get() > 0){ int j = tick.getAndDecrement(); System.out.println(Thread.currentThread().getName() + " 卖出了第" + j + "张票" ); //System.out.println("剩下 " + tick + " 张票" ); }else { System.out.println("票卖完了"); } try { sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } countDownLatch.countDown(); return tick.get(); }); new Thread(station, "station" + i).start(); } countDownLatch.await(); System.out.println((System.currentTimeMillis() - time)); } }

结果

4、使用线程池(Executore框架) import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import static java.lang.Thread.sleep; public class TestThread3 { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); ExecutorService executorService = Executors.newCachedThreadPool(); long time = System.currentTimeMillis(); for (int i = 0; i < 3; ++i){ String name = "station" + i; executorService.execute(new Station(name,countDownLatch)); } countDownLatch.await(); System.out.println((System.currentTimeMillis() - time)); executorService.shutdown(); } } class Station implements Runnable { static CountDownLatch countDownLatch; static AtomicInteger tick = new AtomicInteger(20);//保持多个站台线程间票量一直要用static private final String name; public Station(String name, CountDownLatch countDownLatch){ this.name = name;//给线程命名 this.countDownLatch = countDownLatch; } public String getName() { return name; } @Override public void run(){ while(tick.get() > 0){ if(tick.get() > 0){ System.out.println(getName() + " 卖出了第" + tick.getAndDecrement() + "张票" ); //System.out.println("剩下 " + tick + " 张票" ); }else { System.out.println("票卖完了"); } try { sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } countDownLatch.countDown(); } }

结果



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3