Java基础--线程(2)
来源:互联网 发布:淘宝费用预算 编辑:程序博客网 时间:2024/06/01 13:19
1.线程的优先级别
java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器按照线程的优先级决定应调度那个线程来执行。
线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级是5
Thread.MIN_PRIORITY=1,Thread.MAX_PRIORITY=10,Thread.NORM_PRIORITU=5,
使用下述方法获得或设置线程对象的优先级。
结果:T1和T2并行运行,但是T1的运行几率比较大(比如运行T1到600然后运行几次T2,只有继续运行T1),并不是T1运行完在运行T2,如果不设置优先级,T1和T2间隔基本相同
2.线程同步
例:一存折和一银行卡账户上有3000元,当存折在柜台上取2000时,系统检测到有3000,银行工作人员在给你钱但没有更新数据时,另一个人在取款机上用银行卡取2000,系统将数据更新成1000,银行工作人员,办完业务也将数据更新成1000,这样就出现了错误。
银行卡和存折就相当于两个线程,解决上述问题,就是在一个线程访问数据时,不允许其他线程访问。访问同一份资源的多个线程之间来进行协调,叫做线程同步。
线程同步
在java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性。每个对象都对应于一个可称为互斥锁的标记,这个标记保证在任何时刻,只能又一个线程访问该对象。关键字synchronized来与对象的互斥锁联系,当某个对象synchronized修饰时,表明该对象在任一时刻只能由一线程访问,使用方法如下:
timer类也可写成:
结果是:1000 b=1000
虽然tt对象是锁定的,但是锁定的意义是只是锁定的m1方法(其他对象不能在访问m1方法),m2方法仍然可以运行,否则就会输出100。
将m2方法改成:
3.死锁
所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
学过操作系统的朋友都知道:产生死锁的条件有四个:
1.互斥条件:所谓互斥就是进程在某一时间内独占资源。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
例如:死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等待,而无法执行的情况。分析死锁产生的原因不难看出是由访问共享资源顺序不当所造成的,下面写一个造成线程死锁的例子,希望能对大家理解多线程死锁问题有进一步的理解!如果有人需要编写多线程的系统,当操作共享资源时一定要特别的小心,以防出现死锁的情况!
结果是:flag=0 flag=1然后无限运行,没有出现终止
4.生产者消费者问题
结果:
生产了:WuTou :0
消费了:WuTou :0
生产了:WuTou :1
消费了:WuTou :1
生产了:WuTou :2
消费了:WuTou :2
生产了:WuTou :3
消费了:WuTou :3
生产了:WuTou :4
生产了:WuTou :5
消费了:WuTou :5
消费了:WuTou :4
生产了:WuTou :6
消费了:WuTou :6
生产了:WuTou :7
生产了:WuTou :8
消费了:WuTou :8
生产了:WuTou :9
消费了:WuTou :9
生产了:WuTou :10
生产了:WuTou :11
生产了:WuTou :12
生产了:WuTou :13
生产了:WuTou :14
生产了:WuTou :15
消费了:WuTou :14
消费了:WuTou :15
生产了:WuTou :16
消费了:WuTou :16
生产了:WuTou :17
消费了:WuTou :17
生产了:WuTou :18
消费了:WuTou :18
消费了:WuTou :13
消费了:WuTou :12
生产了:WuTou :19
消费了:WuTou :19
消费了:WuTou :11
消费了:WuTou :10
消费了:WuTou :7
java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器按照线程的优先级决定应调度那个线程来执行。
线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级是5
Thread.MIN_PRIORITY=1,Thread.MAX_PRIORITY=10,Thread.NORM_PRIORITU=5,
使用下述方法获得或设置线程对象的优先级。
int getPriority();
void setPriority(int newPriority);
例如:public class TestPriority { public static void main(String args[]) { Thread t1 = new Thread(new T1()); Thread t2 = new Thread(new T2()); t1.setPriority(Thread.NORM_PRIORITY + 3); t1.start(); t2.start(); }}class T1 implements Runnable { public void run() { for (int i = 0; i < 1000; i++) { System.out.println("T1 " + i); } }}class T2 implements Runnable { public void run() { for (int i = 0; i < 1000; i++) { System.out.println("--------T2: " + i); } }}
结果:T1和T2并行运行,但是T1的运行几率比较大(比如运行T1到600然后运行几次T2,只有继续运行T1),并不是T1运行完在运行T2,如果不设置优先级,T1和T2间隔基本相同
2.线程同步
例:一存折和一银行卡账户上有3000元,当存折在柜台上取2000时,系统检测到有3000,银行工作人员在给你钱但没有更新数据时,另一个人在取款机上用银行卡取2000,系统将数据更新成1000,银行工作人员,办完业务也将数据更新成1000,这样就出现了错误。
银行卡和存折就相当于两个线程,解决上述问题,就是在一个线程访问数据时,不允许其他线程访问。访问同一份资源的多个线程之间来进行协调,叫做线程同步。
线程同步
在java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性。每个对象都对应于一个可称为互斥锁的标记,这个标记保证在任何时刻,只能又一个线程访问该对象。关键字synchronized来与对象的互斥锁联系,当某个对象synchronized修饰时,表明该对象在任一时刻只能由一线程访问,使用方法如下:
public class TestSync implements Runnable { Timer timer = new Timer(); public static void main(String args[]) { TestSync test = new TestSync();//test指向new出来的testSync,testSync //中有timer对象,timer有add方法,t1,t2两个线程都访问了add方法 Thread t1 = new Thread(test); Thread t2 = new Thread(test); t1.setName("t1"); t2.setName("t2"); t1.start(); t2.start(); } public void run() { timer.add(Thread.currentThread().getName()); }}class Timer { private static int num = 0; public void add(String name) { synchronized (this) {//锁定当前对象 num++; try { Thread.sleep(1); } catch (InterruptedException e) { } System.out.println(name + ",你是第" + num + "个使用timer的线程"); } }}
结果是:
t1,你是第1个使用timer的线程
t2,你是第2个使用timer的线程
timer类也可写成:
class Timer { private static int num = 0; public synchronized void add(String name) { //synchronized (this) {//锁定当前对象 num++; try { Thread.sleep(1); } catch (InterruptedException e) { } System.out.println(name + ",你是第" + num + "个使用timer的线程"); }}另一个例子:
public class TT implements Runnable { int b = 100; public synchronized void m1() throws Exception { b = 1000; Thread.sleep(5000); System.out.println("b = " + b); } public void m2(){ System.out.println(b); } public void run() { try { m1(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { TT tt = new TT(); Thread t = new Thread(tt); t.start(); Thread.sleep(1000); tt.m2(); }}
结果是:1000 b=1000
虽然tt对象是锁定的,但是锁定的意义是只是锁定的m1方法(其他对象不能在访问m1方法),m2方法仍然可以运行,否则就会输出100。
将m2方法改成:
public void m2() throws Exception {Thread.sleep(2500);b = 2000;}
并去掉main中的Thread.sleep(1000),并在tt.m2后加System.out.println(tt.b)
结果是:2000 b=2000,m1在睡眠锁定时,m2仍然改掉了b的值,要想解决这个问题,必须要给m2也加上锁,b就等于1000,但实际上b的值是2000所以同步的程序,再一个锁定的对象里的值,需要考虑在其他非同步的程序中是否涉及,如果涉及就需要考虑这个方法是否也要锁定。
在给m2也加同步,并在tt.m2后加System.out,println(tt.b),结果是1000,b=1000,main方法运行中加入了m1将b改为1000,并且m1进入睡眠,此时运行m2,m2也进入睡眠,然后就会打印1000,然后m2唤醒,但是m1,m2都是同步状态,并不能影响到m1的输出,所以输出b=1000.3.死锁
所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
学过操作系统的朋友都知道:产生死锁的条件有四个:
1.互斥条件:所谓互斥就是进程在某一时间内独占资源。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
例如:死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等待,而无法执行的情况。分析死锁产生的原因不难看出是由访问共享资源顺序不当所造成的,下面写一个造成线程死锁的例子,希望能对大家理解多线程死锁问题有进一步的理解!如果有人需要编写多线程的系统,当操作共享资源时一定要特别的小心,以防出现死锁的情况!
public class TestDeadlock implements Runnable { public int flag = 1; static Object o1 = new Object(), o2 = new Object(); public void run() { System.out.println("flag=" + flag); if (flag == 1) { synchronized (o1) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized (o2) { System.out.println("1"); } } } if (flag == 0) { synchronized (o2) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized (o1) { System.out.println("0"); } } } } public static void main(String[] args) { TestDeadlock td1 = new TestDeadlock(); TestDeadlock td2 = new TestDeadlock(); td1.flag = 1; td2.flag = 0; Thread t1 = new Thread(td1); Thread t2 = new Thread(td2); t1.start(); t2.start(); }}
结果是:flag=0 flag=1然后无限运行,没有出现终止
4.生产者消费者问题
public class ProducerConsumer { public static void main(String args[]) { SyncStack ss = new SyncStack(); Producer p = new Producer(ss); Consumer c = new Consumer(ss); new Thread(p).start(); new Thread(c).start(); }}class WoTou { //定义一个生产出来的对象 int id; WoTou(int id) { this.id = id; } public String toString() {//对象返回值 return "WuTou :" + id; }}class SyncStack { //容器使用栈的方式,先进后出 int index = 0; WoTou[] arrWT = new WoTou[6]; public synchronized void push(WoTou wt) { while (index == arrWT.length) { try { this.wait(); //生产满后等待 } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); arrWT[index] = wt; index++; } public synchronized WoTou pop() { while (index == 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); index--; return arrWT[index]; }}class Producer implements Runnable { SyncStack ss = null; Producer(SyncStack ss) { this.ss = ss; } public void run() { for (int i = 0; i < 20; i++) { WoTou wt = new WoTou(i); ss.push(wt); System.out.println("生产了:" + wt); try { Thread.sleep((long) (Math.random() * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } }}class Consumer implements Runnable { SyncStack ss = null; Consumer(SyncStack ss) { this.ss = ss; } public void run() { for (int i = 0; i < 20; i++) { WoTou wt = ss.pop(); System.out.println("消费了:" + wt); try { Thread.sleep((long) (Math.random() * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } }}
结果:
生产了:WuTou :0
消费了:WuTou :0
生产了:WuTou :1
消费了:WuTou :1
生产了:WuTou :2
消费了:WuTou :2
生产了:WuTou :3
消费了:WuTou :3
生产了:WuTou :4
生产了:WuTou :5
消费了:WuTou :5
消费了:WuTou :4
生产了:WuTou :6
消费了:WuTou :6
生产了:WuTou :7
生产了:WuTou :8
消费了:WuTou :8
生产了:WuTou :9
消费了:WuTou :9
生产了:WuTou :10
生产了:WuTou :11
生产了:WuTou :12
生产了:WuTou :13
生产了:WuTou :14
生产了:WuTou :15
消费了:WuTou :14
消费了:WuTou :15
生产了:WuTou :16
消费了:WuTou :16
生产了:WuTou :17
消费了:WuTou :17
生产了:WuTou :18
消费了:WuTou :18
消费了:WuTou :13
消费了:WuTou :12
生产了:WuTou :19
消费了:WuTou :19
消费了:WuTou :11
消费了:WuTou :10
消费了:WuTou :7
0 0
- Java基础 -- 线程2
- Java基础--线程(2)
- Java基础之多线程2
- java基础总结24-java线程2(线程同步)
- 线程之一:JAVA线程基础
- 线程之一:JAVA线程基础
- Java基础复习:线程练习2
- java线程基础——笔记2
- Java基础总结之多线程(2)
- Java之多线程(2)--基础开篇
- java线程学习基础
- Java基础 -- 线程
- JAVA线程基础
- Java 线程基础
- Java线程基础1
- java线程基础
- java基础 线程
- Java 线程基础
- Scala 的参数检查与断言: require, assert, assume 和 ensuring
- Mysql bigint类型 BUG
- [Bullet3]常见物体和初始化
- python基础之模块之os模块
- 打印fastjson对象时,如果内部键值为null,则该键不会打印出来
- Java基础--线程(2)
- [Android新手学习笔记17]-UI控件之ProgressDialog
- Struts2 Key Technologies Primer
- 29.日志路由组件(2)
- angularjs排序
- Java 的参数检查与断言 - Guava Preconditions
- 安卓使用surfaceview+Camera+MediaRecorder实现视频录制
- iOS 10 适配 ATS(app支持https通过App Store审核)
- 李开复:给女儿的一封信