Java中的线程

Posted ssc在路上

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中的线程相关的知识,希望对你有一定的参考价值。

一、概述进程与线程

进程:就是正在运行的程序。
进程是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。

意义:单进程的计算机只能做一件事情,而我们现在的计算机都可以做多件事情。举例:一边玩游戏(游戏进程),一边听音乐(音乐进程)。也就是说现在的计算机是支持多进程的,以在一个时间段内执行多个任务,并且,可以提交CPU的使用率。

线程:是程序的执行单元,执行路径。是程序使用CPU的最基本单位。
单线程:如果程序只有一条执行路径。
多线程:如果程序有多条执行路径。

意义:多线程的存在,不是提高程序的执行速度。其实是为了提高应用程序的使用率。程序的执行其实都是在抢CPU的资源,CPU的执行权。多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的几率抢到CPU的执行权。是不敢保证哪一个线程能够在哪个时刻抢到,所以线程的执行有随机性。

二、线程的理解

1、线程的两种调度模型

(1)分时调度模型

所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间戳

(2)抢占式调度模型

优先让优先级高的线程使用CPU,若果线程的优先级相同,那么会随机选择一个,优先级搞的线程获取的CPU时间戳相对多一些

Java使用的是抢占式的调度模型

2、线程的生命周期

三。线程的创建方式

(1)继承Thread类。

步骤:
 A:自定义类MyThread继承Thread类。
B:MyThread类里面重写run()?
C:创建对象
D:启动线程

 1 /*
 2  * 该类要重写run()方法,为什么呢?
 3  * 不是类中的所有代码都需要被线程执行的。
 4  * 而这个时候,为了区分哪些代码能够被线程执行,java提供了Thread类中的run()用来包含那些被线程执行的代码。
 5  */
 6 public class MyThread extends Thread {
 7 
 8     @Override
 9     public void run() {
10         // 一般来说,被线程执行的代码肯定是比较耗时的。所以我们用循环改进
11         for (int x = 0; x < 200; x++) {
12             System.out.println(x);
13         }
14     }
15 }
16 
17 public static void main(String[] args) {
18     // 面试题:run()和start()的区别?
19     // run():仅仅是封装被线程执行的代码,直接调用是普通方法
20     // start():首先启动了线程,然后再由jvm去调用该线程的run()方法。
21     // 创建两个线程对象
22     MyThread my1 = new MyThread();
23     MyThread my2 = new MyThread();
24 
25     my1.start();
26     my2.start();
27 }

Thread类的一些方法:

如何获取线程对象的名称呢?
public final String getName():获取线程的名称。
如何设置线程对象的名称呢?
public final void setName(String name):设置线程的名称

针对不是Thread类的子类中如何获取线程对象名称呢?
public static Thread currentThread():返回当前正在执行的线程对象
Thread.currentThread().getName()

public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。
当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。

public final void join():等待该线程终止。

public static void yield():暂停当前正在执行的线程对象,并执行其他线程。

public final void stop():让线程停止,过时了,但是还可以使用。
public void interrupt():中断线程。 把线程的状态终止,并抛出一个InterruptedException。

public static void sleep(long millis) 线程休眠

如何获取线程对象的优先级?
public final int getPriority():返回线程对象的优先级
如何设置线程对象的优先级呢?
public final void setPriority(int newPriority):更改线程的优先级。
注意:
线程默认优先级是5。
线程优先级的范围是:1-10。
线程优先级高仅仅表示线程获取的 CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到比较好的效果。

(2)实现Runnable接口

步骤:
A:自定义类MyRunnable实现Runnable接口
B:重写run()方法
C:创建MyRunnable类的对象
D:创建Thread类的对象,并把C步骤的对象作为构造参数传递

 1 public class MyRunnable implements Runnable {
 2 
 3     @Override
 4     public void run() {
 5         for (int x = 0; x < 100; x++) {
 6             // 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用
 7             System.out.println(Thread.currentThread().getName() + ":" + x);
 8         }
 9     }
10 
11 }
12 
13   public static void main(String[] args) {
14         // 创建MyRunnable类的对象
15         MyRunnable my = new MyRunnable();
16 
17         // 创建Thread类的对象,并把C步骤的对象作为构造参数传递
18         // Thread(Runnable target)
19         // Thread t1 = new Thread(my);
20         // Thread t2 = new Thread(my);
21         // t1.setName("林青霞");
22         // t2.setName("刘意");
23 
24         // Thread(Runnable target, String name)
25         Thread t1 = new Thread(my, "林青霞");
26         Thread t2 = new Thread(my, "刘意");
27 
28         t1.start();
29         t2.start();
30     }

实现Runnable接口的好处:

(1)可以避免由于Java单继承带来的局限性

(2)适合多个相同的程序去处理同一个资源的情况,把线程同程序的代码,数据有效的分离,较好的提现了面向对象的设计思想

经典的值得思考的简单代码:(2019-05-27 21:48:00 继续写)

 1 // 大体结构是这样的: 创建Thread对象:new Thread(创建Runnable对象:new Runnable(){ 执行Runnable的run()方法 }){ 执行Thread的run()方法 }.start(); 执行start方法
 2 new Thread(new Runnable(){
 3             @Override
 4             public void run() {
 5                 while (true) {
 6                     try {
 7                         Thread.sleep(500);
 8                     } catch (InterruptedException e) {
 9                         e.printStackTrace();
10                     }
11                     System.out.println("Runnable:" + Thread.currentThread().getName());
12                 }
13             }
14             
15         }){
16             @Override
17             public void run() {
18                 while (true) {
19                     try {
20                         Thread.sleep(500);
21                     } catch (InterruptedException e) {
22                         e.printStackTrace();
23                     }
24                     System.out.println("Thread:" + Thread.currentThread().getName());
25                 }
26             };
27             
28         }.start();

之所以说这个例子比较经典,是因为你要搞懂这个到底在运行哪个run()方法,其实是在执行Thread类的run()方法,因为这个是重写Thread类的run()方法,只有在没有重写Thread类的run()方法的时候,才会去执行父类的run()方法,可以看下Thread类的源码:

1  private Runnable target;
2    
3  @Override
4     public void run() {
5         if (target != null) {
6             target.run();
7         }
8     }

以上是关于Java中的线程的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程与并发库高级应用-工具类介绍

Java多线程与并发库高级应用-工具类介绍

Java中的主线程与UI线程

LockSupport.java 中的 FIFO 互斥代码片段

java中的进程,线程,线程池总结

Java中通过Runnable与Thread创建线程的区别