首页 > 代码库 > Java中线程总结
Java中线程总结
本文简要介绍在 Java 世界中, 线程相关知识。主要包含 线程的创建与销毁;线程安全与同步;线程通讯;注意本文没有什么高深新知识,只缘起前段时间在翻看项目代码的时候,发现有些同学对此有诸多误解,故在此稍微整理一下,以帮助类似同学,同时警醒一下自己。
1. 线程的创建和销毁;
a) .创建线程可以通过继承 Thread 类 或 实现 Runnable 接口, 并重写 run() 方法, 其中的run() 方法即是本线程需要执行的内容.
b). 相比于单独继承 Thread ,Runnable接口配合 Thread 实现会更灵活,并可以通过共享一个Runnable接口实例,在Thread中共享资源.
c). 至于线程销毁,不推荐使用 Thread.Stop()方法, 此方法在使用不当情况下会出现死锁,更多的时候推荐在run()方法中使用额外变量(或条件)结束此方法即可.
2. 线程安全与同步;
a). 对于需要遵循ACID原子一致性的代码段, 可以通过 synchronized(lockKey){} 代码块锁定;
b). 同时 synchronized 关键字可以用来修饰一个方法,表示整个方法都需要遵循ACID原子一致性,值得注意的是,此时其实的lockKey等效于this关键字;
b). 在锁定的代码块中推荐再进行一次必要的条件判断。
3. 线程通讯,在java的世界中可以借助 wait() notify() notifyAll() 这三个方法来完成,这三个方法定义在Object类中,因此所有的对象都可以使用.
4.下面通过简单的几个代码片段来加以说明
a). 演示线程创建与销毁,及线程安全与同步
1 public class ThreadTest implements Runnable { 2 private boolean stop; //是否需要停止运行 3 private int tiketCount = 100000; //总票数 4 private boolean lockTypeIsMethod = true; //是否是提供方法锁定还是代码块 5 6 public boolean isStop() { 7 return stop; 8 } 9 public void setStop(boolean stop) {10 this.stop = stop;11 }12 13 public boolean isLockTypeMethod() {14 return lockTypeIsMethod;15 }16 public void setLockTypeIsMethod(boolean lockTypeIsMethod) {17 this.lockTypeIsMethod = lockTypeIsMethod;18 }19 20 @Override21 public void run() {22 while (tiketCount > 0 && !stop) {23 try {24 Thread.sleep(50); //延时,方便演示25 } catch (InterruptedException e) {26 e.printStackTrace();27 }28 29 //如果是通过锁定方法30 if (lockTypeIsMethod) {31 sale();32 } else {33 synchronized (this) {34 if (tiketCount > 0 && !stop) {35 System.out.println("使用代码块锁定:threadId="36 + Thread.currentThread().getName() + ",ticketNO:" + tiketCount--);37 }38 }39 }40 }41 }42 43 public synchronized void sale() {44 if (tiketCount > 0 && !stop) {45 System.out.println("使用方法锁定:threadId="46 + Thread.currentThread().getName() + ",ticketNO:" + tiketCount--);47 }48 }49 }
1 public static void main(String[] args) throws InterruptedException { 2 ThreadTest threadTest = new ThreadTest(); //共享变量ThreadTest 3 //启用四个线程 4 new Thread(threadTest).start(); 5 new Thread(threadTest).start(); 6 new Thread(threadTest).start(); 7 new Thread(threadTest).start(); 8 //模拟设置共享变量, 9 // 1.交替使用方法体和代码块来进行线程同步实验10 // 2.模拟线程停止11 for (int i = 0; i < 100; i++) {12 Thread.sleep(1000);13 threadTest.setLockTypeIsMethod(i % 2 == 0);14 if (i == 50) {15 threadTest.setStop(true);16 }17 }18 }
b). 演示线程通讯,本处模拟两个线程以生产和消费者角色读写一个集合的示例,其中当集合中有数据的时候通知消费者处理数据,处理完后通知生产者往集合中放入数据
1 //数据仓库 2 public class DataRepository { 3 private List<String> data = http://www.mamicode.com/new ArrayList<>(); 4 private boolean hasData; 5 6 public boolean HasData() { 7 return hasData; 8 } 9 10 public void setHasData(boolean hasData) {11 this.hasData =http://www.mamicode.com/ hasData;12 }13 14 //放入数据15 public synchronized void put(List<String> data) throws InterruptedException {16 //生产者放入数据的时候,如果还有数据则等待.17 if (hasData) {18 wait();19 }20 this.data =http://www.mamicode.com/ data;21 hasData = http://www.mamicode.com/true;22 //放入完毕后通知消费者23 notify();24 }25 26 //读取数据27 public synchronized List<String> get() throws InterruptedException {28 //没有数据则等待29 if (!hasData) {30 wait();31 }32 //获取数据副本返回33 List<String> rs = new ArrayList<>(data);34 data.clear();35 hasData = http://www.mamicode.com/false;36 notify();37 return rs;38 }39 }
1 public class Producer implements Runnable { 2 private DataRepository dataRepository; //数据仓库 3 public Producer(DataRepository dataRepository) { 4 this.dataRepository = dataRepository; 5 } 6 7 public void run() { 8 while (true) { 9 try {10 Thread.sleep(1000);11 } catch (InterruptedException e) {12 e.printStackTrace();13 }14 List<String> temp = new ArrayList<>();15 temp.add("------------");16 temp.add("第一个数据");17 temp.add("第二个数据");18 temp.add("第三个数据");19 temp.add("第四个数据");20 temp.add("------------");21 try {22 dataRepository.put(temp);23 } catch (InterruptedException e) {24 e.printStackTrace();25 }26 }27 }28 }
1 public class Consumer implements Runnable { 2 private DataRepository dataRepository; 3 4 public Consumer(DataRepository dataRepository) { 5 this.dataRepository = dataRepository; 6 } 7 8 public void run() { 9 while (true) {10 try {11 Thread.sleep(1000);12 } catch (InterruptedException e) {13 e.printStackTrace();14 }15 try {16 List<String> data=http://www.mamicode.com/dataRepository.get();17 if(data!=null&&!data.isEmpty()){18 for (String temp :data){19 System.out.println(temp);20 }21 }22 } catch (InterruptedException e) {23 e.printStackTrace();24 }25 }26 }27 }
1 public class Client {2 public static void main(String[] args) throws InterruptedException {3 4 DataRepository dr=new DataRepository();5 new Thread(new Producer(dr)).start(); //启动生产者线程6 new Thread(new Consumer(dr)).start(); //启动消费者线程7 }8 }
后记:
a). 多线程属于较基础的知识,我们首先需要了解其最基本的概念,才能在项目中游刃有余的应用;
b).不管是什么语言,其所需要的理论支持均大同小异;
c).回到最初的那个概念,在多线程中,能不需要线程互相通讯就尽量不要用,能不同步就尽量不要使用线程同步,能不使用多线程就尽量不要使用多线程,说得有些含糊,各位自己去参悟吧.
Java中线程总结