线程调度方法
1.sleep方法
sleep方法在睡眠的时候, 是会释放cpu , 睡眠期间不会抢cpu的
即使睡眠期间没有其他线程占用cpu, 此线程也需要等到睡醒才去抢占cpu
public class Test {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
System.out.println("heheheh");
System.out.println("hhhhhhhhh");
}
}
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("子线程"+i);
}
}
}
2.yield 方法
会释放cpu,但是随手就抢
线程的优先级: 仅仅代表线程的重要或者紧急程度,不代表谁先执行
优先级范围1~10,默认为5,对应的数值越大,说明优先级越高,这个方法的设置一定要在start之前
线程的优先级低并不意味着争抢不到时间片,只是抢到时间片的概率比较低而已
Priority 仅仅能代表重要或者紧急程度, 不能代表执行的顺序
sleep和yeild的区别:
- 都会释放cpu ,但是sleep必须是等到设定的时间以后才会去抢占cpu
yield释放以后迅速的抢占cpu - sleep释放了cpu以后,剩下所有的线程都可以公平竞争抢占cpu
yield释放了cpu以后,只允许和自己优先级相同或者比自己优先级高的线程去抢占cpu
public class Test2 {
public static void main(String[] args) {
MyThread2 thread2 =new MyThread2();
thread2.start();
for (int i = 0; i < 20; i++) {
System.out.println("主线程");
}
}
}
class MyThread2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
Thread.yield();
System.out.println("子线程"+i);
}
}
}
3.join方法
插入到当前线程前面,和当前线程合并在一起
调用者做插队的事情,join写到了哪个线程里面 就会插队到哪个线程前面
public class Test4 {
public static void main(String[] args) {
MyThread4 thread4 = new MyThread4();
thread4.start();
try {
thread4.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 20; i++) {
System.out.println("主线程"+i);
}
}
}
class MyThread4 extends Thread{
@Override
public void run() {
MyThread5 thread5 = new MyThread5();
thread5.start();
try {
// thread5调用join就是thread5要插队
// 写在哪个线程里面, 就是插队到哪个线程前面
thread5.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 20; i++) {
System.out.println("444"+Thread.currentThread().getName()+i);
}
}
}
class MyThread5 extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("555"+Thread.currentThread().getName()+i);
}
}
}
4.线程的生命周期
5.守护线程
如果子线程是守护线程,默认为false, 为前台线程, 设置成true后台线程
如果想要设置成为守护线程一定要在start以前
public class Test5 {
public static void main(String[] args) {
MyThread6 t = new MyThread6();
t.setDaemon(true);
t.start();
for (int i = 0; i < 20; i++) {
System.out.println("主线程");
}
}
}
class MyThread6 extends Thread{
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("子线程"+i);
}
}
}
6.interrupt
以抛异常的方式打断正在sleep中的线程,会产生一个InterruptedException 这个异常
stop()过时了,不建议使用
public class Test6 {
public static void main(String[] args) {
MyThread7 thread7 = new MyThread7();
thread7.start();
thread7.interrupt();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 过时了,不建议使用
thread7.stop();
}
}
class MyThread7 extends Thread{
@Override
public void run() {
System.out.println("困了");
try {
Thread.sleep(60000000);
} catch (InterruptedException e) {
System.out.println("打醒了");
}
System.out.println("醒了");
}
}
7.线程的方法
线程对象.setName();
Thread.currentThread().getName();
Thread.sleep();
线程对象.priority();
线程对象.join();
线程对象.setDaemone();
Thread.yield();
线程对象.interrupt();
8.线程同步
synchronized :同步的关键字
在同步执行完这段代码之前,其他线程不允许进来执行
需要一把锁,必须是唯一的
互斥锁
锁对象可以是任意数据类型
任意锁
设定范围:
1.使用同步代码块
2.同步方法
想要实现线程同步,前提跳进
-
- 拥有共享资源
-
- 至少要拥有两个以及以上的线程
- 如何实现线程同步代码块
-
- 锁 唯一的锁
-
- 确定哪些代码需要同步
-
- synchronized (this){} 用同步代码块把代码包裹起来
public class Ticket implements Runnable{
int ticket = 100;
// 一把锁 是唯一的 只能有一个对象
//Object obj = new Object();
@Override
public void run() {
// ticket = 1
while(true){
// 同步的关键字 num = 1
synchronized (this){// this 指代的是Ticket的对象, ticket只能创建一次对象 锁是唯一的
if(ticket>0){
ticket--;//
System.out.println(Thread.currentThread().getName()+"还剩"+ticket);
}else{
break;
}
}
}
}
}
public class Test2 {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread t = new Thread(ticket, "窗口一");
Thread t2 = new Thread(ticket, "窗口二");
Thread t3 = new Thread(ticket, "窗口三");
Thread t4 = new Thread(ticket, "窗口四");
t.start();
t2.start();
t3.start();
t4.start();
}
}