1、并行和并发

总结:并发和并行是两个非常容易被混淆的概念。它们都可以表示两个或者多个任务一起执行,但是偏重点有些不同。

并发(Concurrency):指的是多个程序可以同时运行的现象,更细化的是多进程可以同时运行或者多指令可以同时运行。

并行(Parallelism):指同时发生的两个并发事件,具有并发的含义,而并发则不一定并行,也亦是说并发事件之间不一定要同一时刻发生。

2、进程和线程

进程:进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的

image-20200526153705106.png

线程:

1、线程与进程相似,但线程是一个比进程更小的执行单位。

2、一个进程在其执行的过程中可以产生多个线程。

3、与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

使用多线程的基础两种方式:
①继承Thread类

  1. public class MyThread extends Thread{
  2. @Override
  3. public void run(){
  4. ....
  5. }
  6. }
  7. class Test{
  8. public static void main(String[] args){
  9. MyThread thread = new MyThread();
  10. thread.start();
  11. }
  12. }

②实现Runnable接口(推荐使用,因为Java是单继承,通过实现接口的方式)

  1. public class MyRunnable implements Runnable{
  2. @Override
  3. public void run(){
  4. ...
  5. }
  6. }
  7. public class Test{
  8. public static void main(String[] args){
  9. Thread thread = new Thread(new MyRunnable);
  10. thread.start();
  11. }
  12. }

Thread常用构造器和方法
image.png
**
currentThread()
返回对当前正在执行的线程对象的引用。

public long getId() 返回此线程的标识符
public final String getName() 返回此线程的名称
public final void setName(String name) 将此线程的名称更改为等于参数 name 。
public final int getPriority() 返回此线程的优先级
public final void setPriority
(int newPriority)
更改此线程的优先级





public static void sleep(long millis)
  1. throws [InterruptedException](../../java/lang/InterruptedException.html)<br /><br /><br /><br /> | 使当前正在执行的线程以指定的毫秒数“休眠”(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。 |

| public final void join()
throws InterruptedException |



等待该线程终止


| |




public static void yield()



| 方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU时间。 | |




public final boolean isAlive()



| 测试这个线程是否还处于活动状态。 | | public void interrupt() | 中断这个线程。
| | public static boolean interrupted() | 测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能 | | public boolean isInterrupted() | 测试线程Thread对相关是否已经是中断状态,但部清楚状态标志 | | public final boolean isDaemon() | 测试这个线程是否是守护线程。 | | publicfinal void setDaemon(boolean on) | 将此线程标记为 daemon线程或用户线程。 | | public static int activeCount() | 此方法返回活动线程的当前线程的线程组中的数量。返回的值只是一个估计值,因为当此方法遍历内部数据结构时,线程数可能会动态更改。 |

活动状态:就是线程已经启动且尚未终止。线程处于正在运行或准备运行的状态。

synchronized是Java中的关键字,是一种同步锁

修饰一个代码块,被修饰的代码块称为同步代码块
作用范围:是大括号{}里面的代码;
作用对象:是调用代码块的对象;

  1. public class Test implements Runnable{
  2. @override
  3. public void run(){
  4. synchronized(this){
  5. ...
  6. }
  7. }
  8. }

修饰一个方法,被修饰的方法称为同步方法
作用范围:是整个方法体内;
作用对象:是调用该方法的对象;

  1. public class Test implements Runnable{
  2. @override
  3. public void run(){
  4. }
  5. public synchronized void task(){
  6. ...
  7. }
  8. public void task(){
  9. synchronized(this){
  10. ...
  11. }
  12. }
  13. }

修饰一个静态方法,被修饰的静态方法
作用范围:是整个静态方法体内;
作用对象:是这个类的所有对象;

  1. public class Test implements Runnable{
  2. @override
  3. public void run(){
  4. }
  5. public static synchronized void task(){
  6. ...
  7. }
  8. }

修饰一个
作用范围:synchronized后面括号括起来的部分;
作用对象:是这个类的所有对象;

  1. public class Test implements Runnable{
  2. @override
  3. public void run(){
  4. synchronized(Test.class){
  5. ...
  6. }
  7. }
  8. }

线程的优先级
1、每个线程都具有各自的优先级,线程的优先级可以在程序中表明该线程的重要性,如果有很多线程处于就绪状态,系统会根据优先级来决定首先使哪个线程进入运行状态
2、java中优先级的范围是1~10,默认的优秀级是5

public static final int MIN_PRIORITY 线程可以拥有的最小优先级。
public static final int NORM_PRIORITY 分配给线程的默认优先级。
public static final int MAX_PRIORITY 线程可以拥有的最大优先级。
  1. public class Test{
  2. Runnable runnable = () ->{
  3. ...
  4. };
  5. Thread thread = new Thread();
  6. // 设置优先级方式一
  7. thread.setPriority(1);
  8. // 方式二
  9. thread.setPriority(Thread.MAX_PRIORITY)
  10. }

注意:
线程优先级具有随机性也就是说线程优先级高的不一定每一次都先执行完。

线程的六中状态

  1. New:新建状态,线程被创建,没有调用start()
  2. Runnable:运行状态,Java线程把操作系统中的就绪和运行两种状态统一称为“运行中”
  3. Blocked:阻塞,线程进入等待状态,线程因为某种原因,放弃了CPU的使用权
  4. Waiting:等待状态
  5. timed_waiting:超时等待状态,超时以后自动返回
  6. terminated:终止状态,当前线程执行完毕

正确的终止一个线程:

  1. public class Test{
  2. private static volatile boolean flag = true;
  3. public static void main(String[] args){
  4. int count = 0;
  5. Runnable runnable = () -> {
  6. while(flag){
  7. ...
  8. if(count==10) flag = false;
  9. }
  10. }
  11. new Thread(runable).strat();
  12. }
  13. }

详解方法:
1、join()方法

public final void join() throws InterruptedException 等待调用join方法的线程结束,再继续执行。
  1. public class Test{
  2. public static void main(String[] args){
  3. Runnable runnable = ()->{
  4. for(int i = 0; i < 10; i++){
  5. ...
  6. }
  7. };
  8. for(int i = 0; i < 10; i++){
  9. ...
  10. }
  11. Thread thread = new Thread(runnable,"子线程");
  12. thread.strat();
  13. // 子线程调用了join()方法,后面的主线程代码只有等到子线程结束了才能执行。
  14. thread.joit();
  15. System.out.println("程序运行结束");
  16. }
  17. }

2、yield()方法

public static void yield() 暂停当前正在执行的线程对象。(谦让)
yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
yield()只能使同优先级或更高优先级的线程有执行的机会。
  1. public class Test{
  2. public static void main(Sting[] args){
  3. Runnable runnable = ()->{
  4. for(int i = 0; i < 50; i++){
  5. if("子线程1".equals(Thread.currentThread.getName)){
  6. Thread.yield();
  7. }
  8. }
  9. };
  10. new Thread(runnable,"子线程1").strat();
  11. new Thread(runnable,"子线程2").strat();
  12. }
  13. }