多线程编程
2016-05-11 16:53
357 查看
Java 线程的创建方法2种
一种继承 Thread
另一种 实现接口Runnable
都要重写run方法。
线程不安全:
private Object obj;
Synchronized(obj)
Obj有多少个,锁就有多少个
或者
Public Synchronized void dosomething(){
.........
}
有多少个线程就有多少个锁
锁的对象为 this
特点:相互独立,互不影响。
线程安全:
Private static Object obj;
Synchronized(obj)
只有一把锁 锁对象为obj;
或者
Public Synchronized static void dosomething(){
.........
}
只有一把锁 锁对象为当前方法的类对象即this.getClass()
特点:操作共享资源时能够线程安全。
线程的工作流程图
锁对象 调用Wait()方法使现在的线程休眠,并且释放锁。
锁对象 调用notify()方法,通知锁对象对应的等待锁列队中的某个线程锁释放了,从而进入就绪状态,但是当该苏醒过来的线程是在调用wait方法之后往下执行代码的。
锁对象 调用notifyAll()方法,与notify不同的是 通知 锁对象对应的锁列队中的所有线程锁释放了。
且 wait notify notifyAll 这三个方法都必须在synchronize对应的方法块中调用。
Sleep(time) 方法是当前线程的方法,调用后该线程将休息一段时间,并不会释放锁,等休息够了再执行后面的代码。
Yield() 让出CPU的使用,释放锁,让优先级高的线程使用。
Thread.interrupt()方法不会中断一个正在运行的线程。它的作用是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。
interrupt方法并不是强制终止线程,它只能设置线程的interrupted状态,而在线程中一般使用一下方式:
while (!Thread.currentThread().isInterrupted() && more work to do){}
线程死锁
public class Car {
private Source
s1;
private Source
s2;
public Car(Source
s1,Source s2) {
// TODO Auto-generated constructor stub
this.s1 =
s1;
this.s2 =
s2;
}
public void go(){
String name = Thread.currentThread().getName();
synchronized (s1) {
System.out.println(name+"
霸占了 "+s1.getName()+"休息2秒后进攻另一个地方");
sleep();
synchronized (s2) {
System.out.println(name+"
霸占了 "+s2.getName()+"休息2秒后迎接胜利");
sleep();
}
}
System.out.println(name+"
成功抵达目的地");
}
public void sleep(){
try {
Thread.sleep(2000);
} catch (InterruptedException
e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void back(){
String name = Thread.currentThread().getName();
synchronized (s2) {
System.out.println(name+"
霸占了 "+s2.getName()+"休息2秒后进攻另一个地方");
sleep();
synchronized (s1) {
System.out.println(name+"
霸占了 "+s1.getName()+"休息2秒后迎接胜利");
sleep();
}
}
System.out.println(name+"
成功抵达目的地");
}
public static void main(String[]
args) {
Source s1 = new Source("南昌");
Source s2 = new Source("上海");
final Car
car1 = new Car(s1,s2);
final Car
car2 = new Car(s1,s2);
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
car1.go();
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
car2.back();
}
}).start();
}
}
死锁的四个条件:
1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
避免死锁的方法就是破坏死锁形成的4个条件就行了。
一种继承 Thread
另一种 实现接口Runnable
都要重写run方法。
线程不安全:
private Object obj;
Synchronized(obj)
Obj有多少个,锁就有多少个
或者
Public Synchronized void dosomething(){
.........
}
有多少个线程就有多少个锁
锁的对象为 this
特点:相互独立,互不影响。
线程安全:
Private static Object obj;
Synchronized(obj)
只有一把锁 锁对象为obj;
或者
Public Synchronized static void dosomething(){
.........
}
只有一把锁 锁对象为当前方法的类对象即this.getClass()
特点:操作共享资源时能够线程安全。
线程的工作流程图
锁对象 调用Wait()方法使现在的线程休眠,并且释放锁。
锁对象 调用notify()方法,通知锁对象对应的等待锁列队中的某个线程锁释放了,从而进入就绪状态,但是当该苏醒过来的线程是在调用wait方法之后往下执行代码的。
锁对象 调用notifyAll()方法,与notify不同的是 通知 锁对象对应的锁列队中的所有线程锁释放了。
且 wait notify notifyAll 这三个方法都必须在synchronize对应的方法块中调用。
Sleep(time) 方法是当前线程的方法,调用后该线程将休息一段时间,并不会释放锁,等休息够了再执行后面的代码。
Yield() 让出CPU的使用,释放锁,让优先级高的线程使用。
Thread.interrupt()方法不会中断一个正在运行的线程。它的作用是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。
interrupt方法并不是强制终止线程,它只能设置线程的interrupted状态,而在线程中一般使用一下方式:
while (!Thread.currentThread().isInterrupted() && more work to do){}
线程死锁
public class Car {
private Source
s1;
private Source
s2;
public Car(Source
s1,Source s2) {
// TODO Auto-generated constructor stub
this.s1 =
s1;
this.s2 =
s2;
}
public void go(){
String name = Thread.currentThread().getName();
synchronized (s1) {
System.out.println(name+"
霸占了 "+s1.getName()+"休息2秒后进攻另一个地方");
sleep();
synchronized (s2) {
System.out.println(name+"
霸占了 "+s2.getName()+"休息2秒后迎接胜利");
sleep();
}
}
System.out.println(name+"
成功抵达目的地");
}
public void sleep(){
try {
Thread.sleep(2000);
} catch (InterruptedException
e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void back(){
String name = Thread.currentThread().getName();
synchronized (s2) {
System.out.println(name+"
霸占了 "+s2.getName()+"休息2秒后进攻另一个地方");
sleep();
synchronized (s1) {
System.out.println(name+"
霸占了 "+s1.getName()+"休息2秒后迎接胜利");
sleep();
}
}
System.out.println(name+"
成功抵达目的地");
}
public static void main(String[]
args) {
Source s1 = new Source("南昌");
Source s2 = new Source("上海");
final Car
car1 = new Car(s1,s2);
final Car
car2 = new Car(s1,s2);
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
car1.go();
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
car2.back();
}
}).start();
}
}
死锁的四个条件:
1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
避免死锁的方法就是破坏死锁形成的4个条件就行了。
相关文章推荐
- python内建函数及属性
- Hibernate中in查询一个问题传多个参数
- 继承Spring AbstractRoutingDataSource实现路由切换
- 通过IL分析C#中的委托、事件、Func、Action、Predicate之间的区别与联系
- Ubuntu16.04下 Matlab2015b安装与激活及注意事项:
- java中super的用法;
- 你确实应该学习并使用的 10 个 C# 特性
- Java Web开发-目录
- [java]编程的智慧(转)
- ECSHOP session 的使用 注意事项 ,ecshop 批发 代码模式切换,普通会员特殊会员切换
- java静态代理和动态代理
- 快速排序算法学习心得(Java实现)
- C语言 文件操作12--文件加密
- C#_串口通信_SerialPort_一个最基础的串口程序
- Java - HashSet
- C++中的vector容器对象学习笔记
- Dubbo-admin 不支持JDK8 解决办法
- C++ typedef用法小结
- iOSDay09C语言函数指针
- iOSDay08之C语言内存管理