我们到底能走多远系列(6)
光阴似箭,我居然也到了需要相亲的年龄。
我已经开始准备向人生成熟的阶段前进,就像一个苹果,从青苹果到成熟,要经历很多,要面对很多,这一路,每一位在我身边的朋友都有你的功劳。
加油,各位,我们都不孤单。
----------------------------------------------------------------
java多线程的一些理解:
关于同步方法,我们不得不需要记住:
1,线程在一个对象上,两个线程不可以调用两个不同的同步方法
2,当一个同步方法已经执行,其他线程还是能够调用这个对象的非同步方法。
selvlet中为了提高响应速度,采用的是在初始化时将一个servlet实例化后放到一个Map中,当需要响应时直接从这个Map中取出实例用就可以了,如此即可提高反复同时调用同个servlet时的响应时间。
而servlet本身多线程的,在对于同一个servlet的调用时,采用的是线程池的方式。(关于线程池,对于tomcat,可以再server.xm中通过<connector>元素在设定线程池中的数目)
所以,玩servlet的都应该明白:servlet是线程非安全的。
网上推荐的避免非安全的方式:
1,使用SingleThread,现在的servlet版本中已经被废弃,可以无视。
2,同步共享数据的操作,在所有的多线程中多用得到。
3,不要使用实例变量,静态变量
静态变量是线程非安全的 实例变量单例模式时是线程非安全的 局部变量是线程安全的
----------------------------------------
多线程控制的精髓应该是控制共享数据从而控制多线程逻辑。
两个线程轮流执行任务:
主程序:
public class MainTest { public static void main(String[] args) { FlgClass flgClass = new FlgClass();//共享数据 //两个线程 Thread t1 = new Thread(new Thread1(flgClass)); Thread t2 = new Thread(new Thread2(flgClass)); t1.start(); t2.start(); } }
共享数据类:
//共享数据 public class FlgClass { private boolean flg; public boolean isFlg() { return flg; } public void setFlg(boolean flg) { this.flg = flg; } }
两个线程:
public class Thread1 implements Runnable { private FlgClass flgClass; Thread1(FlgClass flgClass) { this.flgClass = flgClass; } public void run() { int i = 5; synchronized (flgClass) { // 在一个循环中 while (i > 0) if (flgClass.isFlg()) { System.out.println(Thread.currentThread().getName() + " " + i); flgClass.setFlg(false);//控制共享数据从而控制线程逻辑 flgClass.notify(); --i; } else { try { flgClass.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
public class Thread2 implements Runnable { private FlgClass flgClass; Thread2(FlgClass flgClass) { this.flgClass = flgClass; } public void run() { int i = 5; synchronized (flgClass) { while (i > 0) if (!flgClass.isFlg()) { System.out.println(Thread.currentThread().getName() + " " + i); flgClass.setFlg(true); flgClass.notify(); --i; } else { try { flgClass.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
关于线程池:
//创建一个可重用固定线程数的线程池 ExecutorService pool = Executors.newFixedThreadPool(2);
//创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。 ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
//创建等待队列 BlockingQueue bqueue = new ArrayBlockingQueue(20); //创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。 ThreadPoolExecutor pool = new ThreadPoolExecutor(2,3,2,TimeUnit.MILLISECONDS,bqueue);
分工使现代社会进步!
做一个产品现在都是分工到很细,一个工人只要做好一件事就可以了,比如制造手机,一批工人只做手机屏幕,一批工人做外壳等等这样分工后,提高了生产效率。
我想到传送带上的工作流程:一个工人焊接一个点后,产品就会传下去,下一个工人焊接另一个点,知道最后一个工人拿到的是成品只需要包装一下。
和前辈聊天的时候,他说像网络交互这种程序大多是这样工作的。
所以我想学习下,一个简单的流程模型
实现:
产品类:
/** * * 简化的产品类 作为共享数据,是线程逻辑的操作对象 */ public class Product { // 产品编号 private int id; // 用state来查看产品处在什么阶段 private int state; Product(int id, int state){ this.id = id; this.state = state; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getState() { return state; } public void setState(int state) { this.state = state; } }
主函数:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class PoolTest { public static void main(String[] args) { // 创建一个可重用固定线程数的线程池(生产者线程池) ExecutorService producerPool = Executors.newFixedThreadPool(3); // 包装工人线程池(就是有3个包装工人嘛) ExecutorService packerPool = Executors.newFixedThreadPool(3); // 有5分产品需要操作 Product p1 = new Product(1, 1); Product p2 = new Product(2, 1); Product p3 = new Product(3, 1); Product p4 = new Product(4, 1); Product p5 = new Product(5, 1); // 需要5个生产工人的活 producerPool.execute(new Producer(p1)); producerPool.execute(new Producer(p2)); producerPool.execute(new Producer(p3)); producerPool.execute(new Producer(p4)); producerPool.execute(new Producer(p5)); // 需要5个包装工人的活 packerPool.execute(new Packer(p1)); packerPool.execute(new Packer(p2)); packerPool.execute(new Packer(p3)); packerPool.execute(new Packer(p4)); packerPool.execute(new Packer(p5)); // 关闭线程池 producerPool.shutdown();// 我想在shutdown的时候应该要检查这个pool里的线程都释放了吧 packerPool.shutdown(); } }
生产线程:
public class Producer extends Thread { private Product product; Producer(Product product) { this.product = product; } @Override public void run() { synchronized (product) { while (true) { if (product.getState() == 1) { System.out.println(product.getId() + "号---进入生产阶段---"); try { product.setState(2);// 标记下一个阶段 sleep(500); System.out.println(product.getId() + "号---生产完毕---"); product.notify();// 释放资源,相当于把生产好的产品传送给下一个操作者-->包装 } catch (InterruptedException e) { e.printStackTrace(); } } else if(product.getState() > 1){// 已经进入下一个阶段 break;// 释放线程 }else{// 在生产阶段之前 try { product.wait(); // 产品还不能进入生产阶段 } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
包装线程:
public class Packer extends Thread{ private Product product; Packer(Product product) { this.product = product; } @Override public void run() { synchronized (product) { while (true) { if (product.getState() == 2) { System.out.println(product.getId() + "号---进入包装阶段---"); try { product.setState(3);// 标记下一个阶段 sleep(100); System.out.println(product.getId() + "号---包装完毕---"); product.notify();// 释放资源,相当于把包装好的产品传送给下一个阶段 } catch (InterruptedException e) { e.printStackTrace(); } } else if(product.getState() > 2){// 已经进入下一个阶段 break;// 释放线程 }else{// 在包装阶段之前 try { product.wait(); // 产品还不能进入包装阶段 } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
----------------------------------------------------------------------
努力不一定成功,但不努力肯定不会成功。
共勉。