线程基础和多线程创建

进程 :  正在执行的程序称作为一个进程。  进程负责了内存空间的划分。
 
线程: 线程在一个进程 中负责了代码的执行,就是进程中一个执行路径,
多线程: 在一个进程中有多个线程同时在执行不同的任务。

线程负责了代码 的执行,我们之前没有学过线程,为什么代码可以执行?
运行任何一个java程序,jvm在运行的时候都会创建一个main线程执行main方法中所有代码。



一个java应用程序至少有两个线程, 一个是主线程负责main方法代码的执行,一

个是垃圾回收器线程,负责了回收垃圾。

线程的生命周期:



创建:新创建了一个线程对象

可运行:线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取cpu执行权

运行:就绪状态的线程获取了CPU执行权,执行程序代码。

阻临时塞: 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态

造成阻塞的原因有很多,有两种原因说明一下:

第一,sleep();该方法会是当前线程暂停,但是当时间过后会回到可运行状态下等待获得cpu执行权;

在多线程同步(synchronized)情况下该方法不会释放对象锁,监控状态依然保持,当时间到了又会自动恢复运行状态。

第二,wait();该方法暂停后需要其他线程调用notify()才能重新回到可运行状态;

在多线程同步(synchronized)的情况下,该方法会释放对象锁,当执行notify()或者notifyAll()方发时才会进入等待区等待当前获得对象锁释放锁后竞争锁继续执行。

然后需要注意的是:

wait( ),notify( ),notifyAll( )都不属于Thread类,而是属于Object基础类,也就是每个对象都有wait( ),notify( ),notifyAll( ) 的功能,因为每个对象都有锁,锁是每个对象的基础,当然操作锁的方法也是最基础了。

关于wait()和notify()要注意的是:

在调用 wait()之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用 wait()方法。进入 wait()方法后,当前线程释放锁。在从 wait()返回前,线程与其他线程竞争重新获得锁。如果调用 wait()时,没有持有适当的锁,则抛出 IllegalMonitorStateException,它是 RuntimeException 的一个子类,因此,不需要 try-catch 结构。

nitify()方法也要在同步方法或同步块中调用,即在调用前,线程也必须要获得该对象的对象级别锁,的如果调用 notify()时没有持有适当的锁,也会抛出 IllegalMonitorStateException。

死亡:线程执行完它的任务时。


多线程的好处:

1. 解决了一个进程能同时执行多个任务的问题。
2. 提高了资源的利用率。

多线程 的弊端:
1. 增加cpu的负担。
2. 降低了一个进程中线程的执行概率。
3. 引发了线程安全 问题。
4. 出现了死锁现象。

如何创建多线程?两种方式:

第一种:


1.创建线程的方式:
 自定义一个类继承Thread类,
重写Thread类的run方法 , 把自定义线程的任务代码写在run方法中

 重写run方法的目的是什么?     

        每个线程都有自己的任务代码,jvm创建的主线程的任务代码就是main方法中的所有代码, 自定义线程的任务代码就写在run方法中,自定义线程负责了run方法中代码。

 2. 创建一个Thread的子类的对象,并且调用start方法开启线程。

    注意:一个线程一旦开启,那么线程就会执行run方法中的代码,run方法千万不能直接调用,直接调用run方法就相当调用了一个普通的方法而已,并没有开启新的线程。

第二种:


使用Runnable接口.

该类中的代码就是对线程要执行的任务的定义.

1:定义了实现Runnable接口

2:重写Runnable接口中的run方法,就是将线程运行的代码放入在run方法中

3:通过Thread类建立线程对象

4:将Runnable接口的子类对象作为实际参数,传递给Thread类构造方法

5:调用Thread类的start方法开启线程,并调用Runable接口子类run方法

为什么要将Runnable接口的子类对象传递给Thread的构造函数,因为自定义的run方法所属对象是Runnable接口的子类对象,所以要让线程去执行指定对象的run方法

理解Runnable:

Thread类可以理解为一个工人,Runnable的实现类的对象就是这个工人的工作(通过构造方法传递).Runnable接口中只有一个方法run方法,该方法中定义的事会被新线程执行的代码.当我们把Runnable的子类对象传递给Thread的构造时,实际上就是让给Thread取得run方法,就是给了Thread一项任务.

线程常用的方法:

  •   Thread(String name)     初始化线程的名字
  • setName(String name)    设置线程对象名
  • getName() 返回线程的名字 
  • sleep() 线程睡眠指定的毫秒数。静态的方法, 那个线程执行了sleep方法代码那么就是那个线程睡眠。 
  • currentThread()  返回当前的线程对象,该方法是一个静态的方法, 注意: 那个线程执行了currentThread()代码就返回那个线程 的对象。 
  • getPriority()返回当前线程对象的优先级   默认线程的优先级是5
  • setPriority(int newPriority) 设置线程的优先级    虽然设置了线程的优先级,但是具体的实现取决于底层的操作系统的实现(最大的优先级是10 ,最小的1 , 默认是5)。

猜你喜欢

转载自blog.csdn.net/qq_29569183/article/details/80681290