线程的优先级
线程调度:按照特定的机制为线程分配CPU的时间片段的行为,java程序再运行的时候,由java虚拟机负责线程的调度
线程调度的实现方式:1、分时调度,2、抢占式调度
分时调度:指让所有线程轮流获取CPU的使用权,并为每个线程平均分配CPU的时间片段
抢占式调度:指选择优先级较高的线程执行,如果所有的线程优先级相同,则会随机选择一个线程执行,java虚拟机正是采用这个调度模式。
线程优先级范例一:
1 public class ThreadTest5 {
2
3 public static void main(String[] args) {
4
5 Thread th = new Thread(new Runnable() {
6 @Override
7 public void run() {
8
9 for (int i = 0; i <100 ; i++) {
10
11 System.out.println(Thread.currentThread().getName());
12 }
13
14
15 }
16 });
17 th.setPriority(1);//设置该线程的优先级
18 th.start();//开启这个线程,并执行run方法
19 System.out.println(th.getPriority());//获取该线程的优先级
20
21
22 Thread th2 = new Thread(new Runnable() {
23 @Override
24 public void run() {
25
26 for (int i = 0; i <100 ; i++) {
27
28 System.out.println(Thread.currentThread().getName());
29 }
30
31
32 }
33 });
34 th2.setPriority(10);//设置该线程的优先级
35 th2.start();//开启这个线程,并执行run方法
36 System.out.println(th2.getPriority());//获取该线程的优先级
37
38
39
40
41 }
42 }
注意:自定义的线程和main方法主线程的优先级默认都是5,线程的优先级用数据表示,范围1~10
线程同步
什么是线程安全:多线程应用程序同时访问共享对象时,由于线程之间相互抢占CPU的控制权,会造成一个线程夹在另一个线程的执行过程中运行,会造成错误的执行的过程
synchronized关键字:确保共享对象只能被一个线程访问,这种机制称为线程同步或者线程互斥,java中的线程同步是基于对象锁的概念。
synchronized关键字使用范例
1 public class ThreadTest6 {
2
3 public static void main(String[] args) {
4
5 maipiao maipiao = new maipiao();
6
7 Thread t1 = new Thread(maipiao,"学生");
8 Thread t2 = new Thread(maipiao,"白领");
9 Thread t3 = new Thread(maipiao,"工人");
10
11 t1.start();
12 t2.start();
13 t3.start();
14
15 }
16
17
18
19
20 }
21
22 /**
23 *定义一个线程类
24 */
25 class maipiao implements Runnable{
26
27 private Integer ticket = 100;//定义100张票
28 private Boolean state = true;
29 @Override
30 public void run() {
31
32 while (state){
33 function();
34 }
35
36 }
37
38 /**
39 * 买票的实现方法
40 *synchronized关键字:加在方法上该方法就是一个同步方法,在某一个时间片段只能由一个线程方法该方法
41 */
42
43 public /*synchronized*/ void function(){
44
45 //也可以用同步代码块的方式保持同步
46 synchronized (this){
47 if(ticket<=0){
48 state=false;
49 return;
50 }
51
52 try {
53 Thread.sleep(1000);//让线程睡眠1秒
54 } catch (InterruptedException e) {
55 e.printStackTrace();
56 }
57
58 if(state){
59 System.out.println(Thread.currentThread().getName()+"-抢到了第"+ticket--+"张票");
60 }
61 }
62
63
64 }
65 }
同步方法和同步代码块的作用是一样的,只是控制的范围不一样,范围越大,性能越差,所以一般使用同步代码块来保持线程同步
线程之间的通信
列举3个重要的方法:均是java.lang.Object中的方法,只能在同步方法或者同步代码块中使用,否则会抛出异常
wait()方法:中断方法的执行,使当前线程等待,暂时让出CPU的使用权,并允许其他线程使用该同步方法。
notify()方法:唤醒单个使用同步方法等待的线程
notifyall()方法:唤醒所有使用同步方法等待的线程
生产者消费者问题
1 /* 范例名称:生产者--消费者问题
2 * 源文件名称:ProducerConsumer.java
3 * 要 点:
4 * 1. 共享数据的不一致性/临界资源的保护
5 * 2. Java对象锁的概念
6 * 3. synchronized关键字/wait()及notify()方法
7 */
8
9 public class ProducerConsumer {
10 public static void main(String args[]){
11 SyncStack stack = new SyncStack();
12 Runnable p=new Producer(stack);
13 Runnable c = new Consumer(stack);
14 Thread p1 = new Thread(p);
15 Thread c1 = new Thread(c);
16
17 p1.start();
18 c1.start();
19 }
20 }
21
22
23 class SyncStack{ //支持多线程同步操作的堆栈的实现
24 private int index = 0;
25 private char[] data = new char[6];
26
27 public synchronized void push(char c){
28 if(index == data.length){
29 try{
30 this.wait();
31 }catch(InterruptedException e){}
32 }
33 this.notify();
34 data[index] = c;
35 index++;
36 }
37
38 public synchronized char pop(){
39 if(index ==0){
40 try{
41 this.wait();
42 }catch(InterruptedException e){}
43 }
44 this.notify();
45 index--;
46 return data[index];
47 }
48 }
49
50
51 class Producer implements Runnable{
52 SyncStack stack;
53 public Producer(SyncStack s){
54 stack = s;
55 }
56 public void run(){
57 for(int i=0; i<20; i++){
58 char c =(char)(Math.random()*26+'A');
59 stack.push(c);
60 System.out.println("produced:"+c);
61 try{
62 Thread.sleep((int)(Math.random()*1000));
63 }catch(InterruptedException e){
64 }
65 }
66 }
67 }
68
69
70 class Consumer implements Runnable{
71 SyncStack stack;
72 public Consumer(SyncStack s){
73 stack = s;
74 }
75 public void run(){
76 for(int i=0;i<20;i++){
77 char c = stack.pop();
78 System.out.println("消费:"+c);
79 try{
80 Thread.sleep((int)(Math.random()*1000));
81 }catch(InterruptedException e){
82 }
83 }
84 }
85 }
来源:https://www.cnblogs.com/dsj-66/p/10898330.html