Java 线程和多线程执行过程分析(2)

上面的代码执行时,有三个线程,首先是主线程main创建2个线程对象,并开启这两个线程任务,开启两个线程后主线程输出"main thread over",然后main线程结束。在开启两个线程任务后,这两个线程加入到了就绪队列等待CPU的调度执行。如下图。因为每个线程被cpu调度是随机的,执行时间也是随机的,所以即使mt1先开启任务,但mt2可能会比mt1线程先执行,也可能更先消亡。

Java 线程和多线程执行过程分析

创建线程方式二:

实现Runnable接口,并重写run()方法。

创建子类对象。

创建Thread对象来创建线程对象,并将实现了Runnable接口的对象作为参数传递给Thread()构造方法。

调用start()方法开启线程来执行run()中的任务。

class MyThread implements Runnable { String name; String gender; MyThread(String name,String gender){ this.name = name; this.gender = gender; } public void run(){ int i = 0; while(i<=200) { System.out.println(Thread.currentThread().getName()+"-----"+i); i++; } } } public class CreateThread2 { public static void main(String[] args) { //创建子类对象 MyThread mt = new MyThread("malong","Male"); //创建线程对象 Thread th1 = new Thread(mt); Thread th2 = new Thread(mt); th1.start(); th2.start(); System.out.println("main thread over"); } }

这两种创建线程的方法,无疑第二种(实现Runnable接口)要好一些,因为第一种创建方法继承了Thread后就无法继承其他父类。

3.线程相关的常用方法

Thread类中的方法:

isAlive():判断线程是否还活着。活着的概念是指是否消亡了,对于运行态、就绪态、睡眠态的线程都是活着的状态。

currentThread():返回值为Thread,返回当前线程对象。

getName():获取当前线程的线程名称。

setName():设置线程名称。给线程命名还可以使用构造方法Thread(String thread_name)或Thread(Runnable r,String thread_name)。

getPriority():获取线程优先级。优先级范围值为1-10(默认值为5),相邻值之间的差距对cpu调度的影响很小。一般使用3个字段MIN_PRIORITY、NORM_PRIORITY、MAX_PRIORITY分别表示1、5、10三个优先级,这三个优先级可较大地区分cpu的调度。

setPriority():设置线程优先级。

run():封装的是线程开启后要执行的任务代码。如果run()中没有任何代码,则线程不做任何事情。

start():开启线程并让线程开始执行run()中的任务。

toString():返回线程的名称���优先级和线程组。

sleep(long millis):让线程睡眠多少毫秒。

join(t1):将线程t1合并到当前线程,并等待线程t1执行完毕后才继续执行当前线程。即让t1线程强制插队到当前线程的前面并等待t1完成。

yield():将当前正在执行的线程退让出去,以让就绪队列中的其他线程有更大的几率被cpu调度。即强制自己放弃cpu,并将自己放入就绪队列。由于自己也在就绪队列中,所以即使此刻自己放弃了cpu,下一次还是可能会立即被cpu选中调度。但毕竟给了机会给其它就绪态线程,所以其他就绪态线程被选中的几率要更大一些。

Object类中的方法:

wait():线程进入某个线程池中并进入睡眠态。等待notify()或notifyAll()的唤醒。

notify():从某个线程池中随机唤醒一个睡眠态的线程。

notifyAll():唤醒某个线程池中所有的睡眠态线程。

这里的某个线程池是由锁对象决定的。持有相同锁对象的线程属于同一个线程池。见后文。

一般来说,wait()和唤醒的notify()或notifyAll()是成对出现的,否则很容易出现死锁。

sleep()和wait()的区别:(1)所属类不同:sleep()在Thread类中,wait()则是在Object中;(2)sleep()可以指定睡眠时间,wait()虽然也可以指定睡眠时间,但大多数时候都不会去指定;(3)sleep()不会抛异常,而wait()会抛异常;(4)sleep()可以在任何地方使用,而wait()必须在同步代码块或同步函数中使用;(5)最大的区别是sleep()睡眠时不会释放锁,不会进入特定的线程池,在睡眠时间结束后自动苏醒并继续往下执行任务,而wait()睡眠时会释放锁,进入线程池,等待notify()或notifyAll()的唤醒。

java.util.concurrent.locks包中的类和它们的方法:

Lock类中:

lock():获取锁(互斥锁)。

unlock():释放锁。

newCondition():创建关联此lock对象的Condition对象。

Condition类中:

await():和wait()一样。

signal():和notify()一样。

signalAll():和notifyAll()一样。

4.多线程安全问题和线程同步 4.1 多线程安全问题

线程安全问题是指多线程同时执行时,对同一资源的并发操作会导致资源数据的混乱。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2507d4a2f6ef1914b236b103d5ef53f5.html