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     @Override
21     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 = 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 = hasData;
12     }
13
14     //放入数据
15     public synchronized void put(List<String> data) throws InterruptedException {
16         //生产者放入数据的时候,如果还有数据则等待.
17         if (hasData) {
18             wait();
19         }
20         this.data = data;
21         hasData = 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 = 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=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).回到最初的那个概念,在多线程中,能不需要线程互相通讯就尽量不要用,能不同步就尽量不要使用线程同步,能不使用多线程就尽量不要使用多线程,说得有些含糊,各位自己去参悟吧.

时间: 2024-11-05 13:26:44

Java中线程总结的相关文章

Java中线程封闭之ThreadLocal

在访问共享数据时通常使用同步.若不使用同步则可以将对象封闭在一个线程中达到线程安全的目的,该方法称为线程封闭(Thread Confinement).其中实现线程封闭中规范的方法是使用ThreadLocal类.线程封闭技术一种常用的使用场景是在JDBC Connection对象. public class ConnectionHelper{private final static String URL = "";private final static ThreadLocal<C

多线程(三) java中线程的简单使用

============================================= 原文链接:多线程(三) java中线程的简单使用 转载请注明出处! ============================================= java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依旧是实现了Runnabel接口.考虑到java的

java中线程存活和线程执行的问题!

1 /* 2 下面的程序会出现下面的情况,当Thread-0, Thread-1, Thread-2都被wait的时候,可能会同时苏醒 3 Thread-0 put 4 Thread-1 put 5 Thread-2 put 6 Thread-3 get//在此处,Thread-3拿到锁之后,将所有的等待的线程唤醒,才有了下面的输出 7 Thread-2 put 8 Thread-1 put 9 Thread-0 put 10 */ 11 12 13 虽然多个线程会同时苏醒,但是只有一个能获得c

Java中线程同步的理解 - 其实应该叫做Java线程排队

Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等. 当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程"同步"机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团. 同步这个词是从英文synchronize(使同时发生)翻译过来的.我也不明白为什么

线程的生命周期 - 理解Java中线程的状态

刚刚开始学cocos2-x,仅仅是按照教程把已经安了一般Android的开发环境的eclipse重新升级到安装好cdt和ndk就花了我几十小时,差点都要放弃了. 参考博客 D:\cocos2d-x\cocos2d-x-2.2.3\cocos2dx\platform\third_party\android\prebuilt 说说大概的过程: 下载ndk插件,ndk包,cdt插件.最开始我按照书上的下载了cocos2d-x 2.0.1,希望跟书上统一起来,这样以后学习的时候可以参考书上的也不会遇到太

Java中线程顺序执行

现有线程threadone.threadtwo和threadthree,想要的运行顺序为threadone->threadtwo->threadthree,应该如何处理?这里需要用到一个简单的线程方法join(). join()方法的说明:join方法挂起当前调用线程,直到被调用线程完成后在继续执行(join() method suspends the execution of the calling thread until the object called finishes its ex

java中线程的状态

java中线程有哪些状态? Thread类有一个内部的枚举,State 1.NEW 创建了一个Thread对象,还没有执行start之前,状态为NEW 2.RUNNABLE 调用了Thread的start()方法,状态变为 RUNNABLE 3.BLOCKED 正在等待获取锁,状态为BLOCKED.例如synchronized 4.WAITING 调用 Object.wait() 或 join() 方法后,线程进入WAITING状态.调用wait()方法需要通过notify()或notifyAl

Java中线程的实现:

Java中线程的实现: 一.线程简介: 实现的两种方式为: 1.Thread类 2.Runnable接口 都在java.lang中 都有共通的方法:public void run() 二.线程常用方法 线程启动:start() 线程睡眠:sleep() 线程抢占:join() 线程让步:yield() 三.线程实例 实例一:Thread类实现 class Xc extends Thread   //创建线程所需要继承的类 { public void run()            //run方

Java中线程(Thread)知识概括

Java中线程(Thread)知识概括 进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行. 一个进程中至少有一个线程. 例如:Java VM 启动的时候会有一个进程java.exe.该进程中至少一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中.该线程称之为主线程.jvm启动不止一个线程,还有负责垃圾回收机制等线程. 如何在自定义的代码中,自定义一个线程呢

java中线程分两种,守护线程和用户线程。

java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性,默认为用户线程. 区别:主线程结束后用户线程会继续运行,JVM存活:主线程结束后,如果没有用户线程,都是守护线程,则JVM结束. public class Mytest extends Thread { public void run() { for(int i=0;;i++){ try { Th