线程和进程的区别
1. 线程共享相同的数据,线程间通信更加的容易,而进程都有自己的数据。
2. 线程更加的轻量级,创建和销毁单个线程比发起进程开销要小的多。
3.
线程状态(包含线程同步的情况)
中断:线程运行过程中,因为某个原因被暂停运行,目的是使其它线程获得运行的机会。
如果一个线程被阻塞就无法检查其中断状态
线程的属性
线程优先级:线程默认情况下继承父线程的优先级。
守护线程:惟一责任是为其它线程服务,当只剩下守护线程了JVM就退出了。
线程组
作用:同时对一组线程进行操作。
步1:创建:ThreadGroup g=new ThreadGroup(”groupName”);
步2:添加:Thread t=new Thread(g,threadName);
线程的未检查异常处理
作用:处理run()方法中的未检查异常
处理器必须实现Thread.UncaughtExceptionHandler接口。
接口只有一个方法,uncaughtException(Thread t, Throwable e) 出现未检查异常时调用。
此方法执行的具体步骤如下:
1. 如果该线程组还有父线程组,则调用父线程组的uncaughtException()方法。
2. 否则,如果此方法返回一个非null处理器,则调用该处理器。
3. 否则,如果Throwable是一个ThreadDeath实例,则什么都不做。
4. 否则,线程的名字和Throwable的堆栈踪迹将被输出到System.err上。
5.
线程的创建方法
方法1:推荐使用
|
步1:实现Runnable接口,并在run()方法中定义要做的事情。
|
class MyRunnable implments Runnable{
public void run(){do something;}
}
|
步2:创建一个MyRunnable类
|
Runnable mr=new MyRunnable();
|
步3:由Runnable构造一个Thread对象
|
Thread t=new Thread(mr);
|
步4:启动一个线程
|
t.start();
|
方法2:
|
步1:直接继承Thread类,覆盖run()方法
|
Class MyThread extends Thread{
public void run(){do something;}
}
|
步2:创建一个MyThread类的对象
|
Thread t=new MyThread();
|
步3:启动一个线程
|
t.start();
|
线程的并行运行(重要)
当多个线程并行运行并且都要访问临界资源时,由于条件竞争,会产生数据腐蚀现象,还会产生死锁现象.
解决多线程并行运行所产生的问题的方法
1. 同步锁机制 采用JDK5.0引进的ReentrantLock类,功能比2强大
2. 同步锁机制 采用Synchronized关键字
3. 阻塞队列 4种 继承自java.util.current.BlockingQueue接口
4. 同步队列 1种 继承自java.util.current.BlockingQueue接口
5. 同步器 如:障栅 倒计时门 同步队列 信号量
提高线程组访问效率和管理效率:
1. 执行器 包含了线程池的使用
同步的建议
1. 正确的使用同步可以保证其它任何方法都不会看到对象处于不一致的状态中。
2. 正确的使用同步可以保证对象从一种一致的状态转变到另一种一致的状态。
3. 为了在线程之间可靠的通信,以及为了互斥访问,同步是需要的。
4. 对可变共享数据,特别是作用在它们上面的写操作,一定要加同步。
5. 一般双重检查模式并不能正确的工作,除非共享变量是原语值而不是引用值。
6. 同步区域应该做尽可能少的动作,同步过多增加死锁降低性能。
7. 避免使用线程组
8. 总是在while循环模式来调用wait()
Synchronized (obj){
while(condition does not hold){obj.wait()…}
}
9. 对访问共享变量的所有方法都要考虑是否加锁,因为若有的不加锁可造成数据错误
对象的锁机制
1. 每个对象都有一个互斥锁(隐式锁),且每个锁都有一个隐式条件,且这个锁在一个时间点上只可以分配给满足条件的一个线程。
2. 有两种获得对象锁的途径,通过调用一个同步方法或调用一个同步块。
3. 锁是可重入的,一个线程获得了锁,它可以再次获得,同时会增加锁的持有计数。
4. 锁是递归的,可嵌套的
5.一个锁对象可以有一个或多个相关联的条件对象。
同步锁机制 采用ReentrantLock类
ReentrantLock和Synchornized有同样的语意,但是它的功能强大些。
ReentrantLock可以有多个条件对象即Condition对象,利用条件对象作为控制条件。
ReentrantLock 的使用
|
1
|
Lock myLock=New ReetrantLock();
|
//创建一个锁对象
|
Lock fairLock=New ReetrantLock(true);
|
//创建一个公平锁对象
|
Condition myCondition;
|
//创建一个条件对象
|
2
|
myLock.lock();
|
//获取锁,可能阻塞
|
myLock.tryLock();
|
//试图获得锁,不阻塞
|
myLock.tryLock(100,TimeUnit.MILLISECONDS);
|
//为tryLock设置锁超时
|
3
|
myCondition= myLock.newCondition();
|
//获得锁的条件对象
|
4
|
while(等待条件成立){myCondition.await()};
|
//等待条件成立时等待
|
5
|
myCondition.singalAll();
myCondition.singal();
|
//激活等待线程
|
6
|
myLock.unlock();
|
//释放锁
|
注
|
tryLock()若没有获得锁,则其可以不阻塞而去干别的事。
tryLock()若调用时获得锁则立即获得锁,而不管是否有线程已经等待了很久。
tryLock(,)若在等待时被中断,将抛出InterruptException异常,可以打破死锁
await()在被激活、到达超时、被中断时await()将返回。
await()在等待时被中断将抛出InterruptException异常。
|
|
java.util.current.locks.Lock
java.util.current.locks.ReetrantLock
java.util.current.locks.ReetrantReadWriteLock
java.util.current.locks.Condition
|
Synchronized 进行同步
|
synchronized给方法加锁,作用域为一个方法。
|
public synchronized method()throws InterruptedException{
while(condition){wait();} //等待
......
notifyAll();//notify() 激活其它等待线程
}
|
synchronized给对象加锁,作用域为整个对象。
|
synchronized(object){
while(condition){wait();} //等待
......
notifyAll();//notify() 激活其它等待线程
}
|
注:隐式锁只有一个条件。
|
阻塞队列
|
1
|
ArrayBlockingQueue
|
循环数组实现,可指定容量和公平性。
|
2
|
LinkedBlockingQueue
|
链表实现,可指定容量。
|
3
|
PriorityBlockingQueue
|
堆实现,无限的阻塞优先级队列。
|
4
|
DelayQueue
|
无界的,阻塞时间有限的阻塞队列,实现了Delay接口。
|
阻塞队列:其实就是为了解决生产者消费者问题由JDK提供的队列。
阻塞队列操作
|
方法
|
动作
|
失败时动作
|
add
|
增加一个元素
|
若队列满,则抛异常
|
remove
|
移出并返回头部元素
|
若队列空,则抛异常
|
element
|
返回队列头部元素
|
若队列空,则抛异常
|
offer
|
添加一个元素并返回true
|
若队列满,返回false
|
poll
|
移出并返回头部元素
|
若队列空,返回null
|
peek
|
返回队列头部元素
|
若队列空,返回null
|
put
|
添加一个元素
|
若队列满,阻塞
|
take
|
移出并返回头部元素
|
若队列空,阻塞
|
死锁
优化:把锁的粒度加粗,不要握有多个锁。
API
|
Thread.currentThread()
|
静态方法,获得当前线程
|
Thread.currentThread().isInterrupted()
|
实例方法,检查是否有线程已被中断,不会改变中断状态。
|
Thread.isAlive()
|
实例方法,测试线程是否处于活动状态。
|
Thread.isDaemon()
|
实例方法,测试该线程是否为守护线程。
|
Thread. getThreadGroup()
|
实例方法,返回该线程所属的线程组。
|
Thread.interrupt()
|
中断线程
|
|
Thread.currentThread().interrupted()
|
静态方法,检查当前线程是否被中断,若是则清除其中断状态。
会打断线程的睡眠状态
|
Thread.sleep()
|
静态方法,中断当前正在执行的线程,且不释放对象的锁标记。
|
Thread.yield()
|
静态方法,中断当前正在执行的线程。
|
Thread.dumpStack()
|
静态方法,打印当前线程的堆栈跟踪。
|
join
|
调用某线程的该方法,将当前线与其合并,即等待该线程结束,在执行当前线程
|
Object.wait()
|
调用此方法时必须锁定该对象,等待,且放锁,只有用notfiy唤醒
|
分享到:
相关推荐
JavaThread
### Java Thread用法详解 #### 一、Java线程基础概念与重要性 在Java编程语言中,线程是程序执行的基本单位之一,它能够帮助我们实现多任务处理,提高程序运行效率。Java中的线程主要通过`java.lang.Thread`类来...
本资料“Java Thread Programming”由Paul Hyde提供,包含了关于Java线程编程的理论知识和实践代码,旨在帮助开发者深入理解和熟练掌握Java线程。 首先,我们来了解一下Java中线程的基本概念。在Java中,可以通过两...
在Java编程语言中,线程(Thread)是执行单元,它允许程序同时执行多个任务。在"JAVA thread"这个主题中,我们主要关注的是如何在Java中创建和管理线程,以及如何通过线程实现并发执行,就像"龟兔赛跑"这个小游戏所...
Java Thread Dump 分析 Java Thread Dump 分析是 Java 应用程序性能优化的重要工具之一。Thread Dump 是 JVM 的一个快照,记录了当前所有线程的状态,包括线程的 ID、名称、状态、锁信息等。通过分析 Thread Dump,...
本资源“Java Thread Programming (Sams)”提供了详细的线程编程知识,结合了理论与实际代码,旨在帮助开发者深入理解并熟练掌握Java线程。 1. **线程概念** - 线程是操作系统调度的基本单位,一个进程可以包含多...
java 應用 thread 的小程式 計算 time 的
Java线程分析工具(TDA)是一款专为Java开发者设计的强大工具,用于解析和理解Java应用程序的线程转储(thread dump)。线程转储是Java虚拟机(JVM)在特定时刻生成的一种快照,其中包含了应用程序中所有活动线程的状态...
为保证不会出现卖出同一个票数,要java多线程同步锁。 设计思路:1.创建一个站台类Station,继承Thread,重写run方法,在run方法里面执行售票操作!售票要使用同步锁:即有一个站台卖这张票时,其他站台要等这张票卖...
各种 Java Thread State 第一分析法则
Java线程转储(Thread Dump)是Java应用程序在特定时间点对所有运行线程的状态快照,它包含每个线程的详细信息,如线程ID、线程名称、线程状态以及栈轨迹。分析Java线程转储对于诊断Java应用程序中的性能问题、死锁...
Java Thread在JVM中的实现与理解 Java Thread是Java编程语言中处理并发执行的基本单元,它在Java虚拟机(JVM)中有着重要的地位。本文将深入探讨Java Thread的语法特性以及其在JVM内部的编译结果,帮助开发者更好地...
Java Thread Dump Analyzing
### JStack和Java Thread Dumps分析 #### 一、引言 在Java应用程序开发与维护过程中,时常会遇到性能瓶颈或死锁等问题。这些问题往往难以定位,尤其当系统处于高负载下时,更是如此。此时,`JStack`工具便显得尤为...
Java Thread多线程全面解析涵盖了Java编程中关于线程的重要概念和实践技巧。在Java中,多线程是并发编程的基础,允许程序同时执行多个任务,提高系统资源利用率和应用程序的响应速度。 线程的生命周期包括五个基本...
Java线程(JavaThread)是Java程序中执行的独立单元,它是Java多线程编程的基础。在Java中,每个应用程序至少有一个线程,通常被称为"主线程",用于执行程序的主要逻辑。Java线程允许程序同时执行多个任务,极大地...
在深入探讨Java线程(Java Thread)的基本概念与创建方式之前,我们首先应当明确线程在计算机科学中的地位。线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以...