Java学习路线-14:多线程编程

举报
彭世瑜 发表于 2021/08/14 00:06:43 2021/08/14
【摘要】 第1 章 : Java多线程编程 2 进程与线程 进程 系统进行资源分配和调度的基本单位 线程 在进程基础上划分的更小的程序单元,操作系统能够进行运算调度的最小单位 Java多线程编程语言 3 Thread类实现多线程 1、继承Java.lang.Thread实现多线程 覆写run方法 start启动线程 每一个线程对象只能启动一次,多次启动就会抛出异常 ...

第1 章 : Java多线程编程

2 进程与线程

进程 系统进行资源分配和调度的基本单位
线程 在进程基础上划分的更小的程序单元,操作系统能够进行运算调度的最小单位

Java多线程编程语言

3 Thread类实现多线程

1、继承Java.lang.Thread实现多线程
覆写run方法
start启动线程

每一个线程对象只能启动一次,多次启动就会抛出异常

native

JNI Java Nativa Interface 本地接口,针对不同操作系统有不同的实现

class MyThread extends Thread{ private String name; public MyThread(String name){ this.name = name; } @Override public void run(){ for (int i =0 ; i< 3; i++) { System.out.println(this.name + " -> " + i); } }
}

class Demo{ public static void main(String[] args) { new MyThread("A").start(); new MyThread("B").start(); new MyThread("C").start(); /** A -> 0 A -> 1 A -> 2 C -> 0 B -> 0 B -> 1 B -> 2 C -> 1 C -> 2 */ }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

4 Runnable接口实现多线程

JDK >= 1.8 变为函数式接口
Thread类有单继承局限

class MyThread implements Runnable{ private String name; public MyThread(String name){ this.name = name; } @Override public void run(){ for (int i =0 ; i< 3; i++) { System.out.println(this.name + " -> " + i); } }
}

class Demo{ public static void main(String[] args) { Thread t1 = new Thread(new MyThread("A")); Thread t2 = new Thread(new MyThread("B")); Thread t3 = new Thread(new MyThread("C")); t1.start(); t2.start(); t3.start(); /** A -> 0 A -> 1 A -> 2 C -> 0 B -> 0 B -> 1 C -> 1 C -> 2 B -> 2 */ }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

利用Runnable + Lambda实现

class Demo{ public static void main(String[] args) { for(int i=0; i< 3; i++) { String name = "对象-" + i ; Runnable run = ()->{ for(int j=0; j< 3; j++) { System.out.println(name + "-> " + j); } }; new Thread(run).start(); } /** 对象-0-> 0 对象-0-> 1 对象-0-> 2 对象-1-> 0 对象-2-> 0 对象-1-> 1 对象-1-> 2 对象-2-> 1 对象-2-> 2 */ }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

利用Thread + Lambda实现

class Demo{ public static void main(String[] args) { for(int i=0; i< 3; i++) { String name = "对象-" + i ; new Thread(()->{ for(int j=0; j< 3; j++) { System.out.println(name + "-> " + j); } }).start(); } /** 对象-0-> 0 对象-0-> 1 对象-0-> 2 对象-1-> 0 对象-2-> 0 对象-1-> 1 对象-1-> 2 对象-2-> 1 对象-2-> 2 */ }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

多线程优先考虑Runnable 实现,永远都是Thread.start() 启动

5 Thread与Runnable关系

class Thread implements Runnable

  
 
  • 1

Thread 代理类
MyThread implements Runnable 实际业务

使用了代理设计模式

Thread t = new Thread(new MyThread());

  
 
  • 1

Thread类启动多线程调用的是start()方法,而后启动run()方法
Thread类接收Runnable 接口对象,调用start()方法后,会启动Runnable 接口对象的run()方法

多线程实质上在于多个线程可以进行同一资源的抢占

Thread 描述的是线程
Runnable 描述资源


class MyThread implements Runnable{ private int ticket = 5; public void run() { while (true){ if(ticket > 0){ System.out.println(ticket-- ); }else{ break; } } }
}

public class Demo { public static void main(String[] args) { MyThread t = new MyThread(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); t1.start(); t2.start(); t3.start(); /** * 5 * 3 * 2 * 1 * 4 */ }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

6 Callable接口实现多线程

JDK >= 1.5
java.util.concurrent.Callable

@FunctionalInterface
public interface Callable<V> { V call() throws Exception;
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5

继承关系

class Thread implements Runnable

public interface RunnableFuture<V> extends Runnable, Future<V>

public class FutureTask<V> implements RunnableFuture<V> {


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ExecutionException;

class MyThread implements Callable<String>{ public String call() { return "线程执行完毕"; }
}

public class Demo { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<String> task = new FutureTask<String>(new MyThread()); new Thread(task).start(); System.out.println(task.get()); // 线程执行完毕 }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

区别 Callable Runnable
Runnable JDK1.0 只有run方法,没有返回值
Callable JDK1.5 提供call方法,有返回值

7 多线程运行状态

线程生命周期

创建 start()
就绪 
运行 run()
阻塞 
终止

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

第2 章 : 线程常用操作方法

8 线程的命名和取得

获取当前线程对象

public static native Thread currentThread();

  
 
  • 1

线程自动命名,使用 static

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;


class MyThread implements Runnable { public void run() { System.out.println(Thread.currentThread().getName()); }
}

public class Demo { public static void main(String[] args) throws ExecutionException, InterruptedException { MyThread t = new MyThread(); new Thread(t, "线程A").start(); new Thread(t).start(); new Thread(t, "线程B").start(); /** * 线程A * 线程B * Thread-0 */ }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

主线程

public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println(Thread.currentThread().getName()); // main }

  
 
  • 1
  • 2
  • 3
  • 4

主线程可以创建若干子线程
主线程控制主体流程
子线程执行耗时操作

9 线程休眠

线程暂缓执行

Exception 必须处理

class InterruptedException extends Exception

public static native void sleep(long millis) throws InterruptedException;
public static void sleep(long millis, int nanos) throws InterruptedException;

  
 
  • 1
  • 2
  • 3
  • 4

休眠线程

public class Demo { public static void main(String[] args) { new Thread(()->{ for (int i= 0; i< 3; i++){ System.out.println(i); // 暂停一秒 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

10 线程中断

中断线程执行

public void interrupt()

  
 
  • 1

判断线程是否被中断

public boolean isInterrupted()

  
 
  • 1

所有线程都可以被中断,中断异常必须处理

public class Demo { public static void main(String[] args) { Thread t = new Thread(() -> { // 暂停10秒 try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } }); t.start(); if (!t.isInterrupted()) { t.interrupt(); } // 抛出异常 sleep interrupted }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

11 线程强制运行

线程独占资源,一直到线程执行结束

public final void join() throws InterruptedException

  
 
  • 1
public class Demo { public static void main(String[] args) { Thread mainThread = Thread.currentThread(); Thread t = new Thread(() -> { // 强制执行主线程 try { mainThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } }); t.start(); for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } // 抛出异常 sleep interrupted }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

12 线程礼让

yield 产生;让步

每一次调用yield()方法只会礼让一次当前的资源

public static native void yield();

  
 
  • 1

public class Demo { public static void main(String[] args) { Thread t = new Thread(() -> { for (int i = 0; i < 30; i++) { System.out.println("礼让资源"); Thread.yield(); System.out.println(Thread.currentThread().getName() + " " + i); } }); t.start(); for (int i = 0; i < 30; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

13 线程优先级

线程优先级越高,越可能先执行,可能优先抢占到资源

public final int getPriority()

public final void setPriority(int newPriority)

  
 
  • 1
  • 2
  • 3

优先级常量

MIN_PRIORITY = 1;
NORM_PRIORITY = 5;
MAX_PRIORITY = 10;

  
 
  • 1
  • 2
  • 3

主线程优先级,和默认优先级都是中等优先级 5

public class Demo { public static void main(String[] args) { System.out.println(Thread.currentThread().getPriority()); // 5 }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

文章来源: pengshiyu.blog.csdn.net,作者:彭世瑜,版权归原作者所有,如需转载,请联系作者。

原文链接:pengshiyu.blog.csdn.net/article/details/103059779

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。