线程调度
线程休眠
sleep 是 Thread 类中定义的方法,要调用它只能通过 Thread 对象来调用,或者直接通过类来调用,因为它是静态方法
+ - 交替输出
i == 50 + 的线程休眠 10 s,+ 不再执行,而执行 -
实际情况
i == 50 - 暂停执行,而执行 +
sleep 方法调用和其他方法不一样
其他方法,谁调用谁执行
sleep 不看谁调用,而看在哪调用
在哪调用,则针对对应的线程进行休眠,而不是哪个线程调用,哪个线程休眠
不看谁调 而看在哪调
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(()->{
for (int j = 0; j < 100; j++) {
System.out.println("++++++++++++++++++" + j);
}
});
thread.start();
for (int i = 0; i < 100; i++) {
if(i == 50){
try {
thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i+"-------------------");
}
}
}
线程合并
将指定的线程加入到当前线程中,join
甲乙两个线程,某个时间点在甲线程中调用了乙线程的 join 方法,表示从当前时刻起,线程乙合并到了线程甲中,线程乙会独占 CPU 资源,线程甲进入阻塞状态,当线程乙全部执行完毕之后,线程甲继续执行
public class JoinRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(i + "----------------JoinRunnable");
}
}
}
public class Test {
public static void main(String[] args) {
JoinRunnable joinRunnable = new JoinRunnable();
Thread thread = new Thread(joinRunnable);
thread.start();
for (int i = 0; i < 100; i++) {
if(i == 10){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i + "++++++++++++main");
}
}
}
join() 无参数
join(long millis) 传毫秒参数
区别:合并进来的线程任务执行情况,join() 合并进来的线程会一直占用 CPU 资源,直到任务执行完毕,join(long millis) 合并进来的线程不会一直占用 CPU 资源,而是根据时间参数占用
public class JoinRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i + "----------------JoinRunnable");
}
}
}
public class Test {
public static void main(String[] args) {
JoinRunnable joinRunnable = new JoinRunnable();
Thread thread = new Thread(joinRunnable);
thread.start();
for (int i = 0; i < 100; i++) {
if(i == 10){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i + "++++++++++++main");
}
}
}
线程同步
Java 中允许多线程并行访问,同一个时间段内多个线程同时完成各自操作
当多个线程同时操作一个共享数据时,可能会导致数据不准确的情况出现
线程同步就是给线程上锁
同步和异步
同步:两个线程按顺序执行
异步:两个线程同时执行
上锁是实现同步的一种方式
同步是最终的结果,上锁是实现该结果的具体方式
上锁,给要上锁的方法添加 synchronized 关键字
public class Account implements Runnable {
private static int num;
@Override
public synchronized void run() {
num++;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "是当前的第" + num + "位访客");
}
}
public class Test {
public static void main(String[] args) {
Account account = new Account();
Thread thread1 = new Thread(account,"张三");
Thread thread2 = new Thread(account,"李四");
thread1.start();
thread2.start();
}
}
synchronized 在进行锁定的时候,还需要判断被锁定的资源有几个,如果被锁定的资源只有一个,则可以实现同步,如果被锁定的资源不止一个,则仍然不会实现同步
public class Account implements Runnable {
private static int num;
@Override
public void run() {
synchronized (Account.class){
num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "是当前的第" + num + "位访客");
}
}
}
public class Account implements Runnable {
private static int num;
@Override
public void run() {
synchronized (this){
num++;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "是当前的第" + num + "位访客");
}
}
}
public class Test {
public static void main(String[] args) {
Account account1 = new Account();
Account account2 = new Account();
Thread thread1 = new Thread(account1,"张三");
Thread thread2 = new Thread(account2,"李四");
thread1.start();
thread2.start();
}
}