首页 > 编程 > Java > 正文

Java多线程(一)

2019-11-06 07:59:07
字体:
来源:转载
供稿:网友

一、进程与线程

进程:是程序的一次执行过程,从代码加载、执行到执行完毕的一个完整过程,这个过程也是进程本身从产生、发展到最后消亡的过程。

一个进程就代表一个程序。操作系统能运行多个同时进程。多进程是实现并发的一种有效手段。

线程:线程和进程一样,都是实现并发的一个基本单位。线程是在进程的基础上进行的进一步的划分。

多线程是说一个进程在执行过程中可以产生多个线程,这些线程可以同时存在、同在运行。

二、java中线程的实现

第一种:继承Thread类,重写run()方法,此方法为线程的主体,

要开启线程需要调用start()方法,而不能直接调用run()方法,若直接调用run()方法不会开启线程,仍然是在单线程里执行。

为什么启动线程不能直接使用run()方法呢?

因为线程的运行需要本机操作系统的支持。下面为start()方法在Thread类中的定义:

	public synchronized void start(){		if(threadStatus != 0)			throw new IllegalThreadStateException();		...		start0();		...	}	PRivate native void start0();

一般在重复调用start()方法时会抛出“IllegalThreadStateException”异常,

而且实际上此处真正调用的是start0()方法,此方法在声明处使用的native关键字声明,此关键字表示调用本机的操作系统函数,因为多线程的实现依靠底层操作系统的支持。

第二种:实现Runnable接口

Runnable接口中只定义了run()一个抽象方法。

三、Thread和Runnable

联系:Thread类实现了Runnable接口,下面是Thread类的定义:

由此可见,Thread类中的run()方法调用的是Runnable接口中的run()方法,若是要继承Thread类实现多线程,则必需覆写run()方法。

区别:

继承Thread类不适合多个线程共享资源,因为每创建一个线程对象,每个对象都有自己的属性、方法,也都有自己的run()方法。

实现Runnable接口,方便实现资源共享:可以使用一个实现Runnable接口的类的对象创建多个线程,它们共用一个Runnable对象,共用里面的属性、方法,共用run()方法。

四、线程的状态

1.创建状态:创建一个线程对象后就进入创建状态,此时它已经有了相应的内存空间和其他资源,处于不可运行状态。

2.就绪状态:调用start()方法后就开启了线程,线程进入就绪状态,进入线程队列排队,等待CPU服务,已经具备运行条件。

3.运行状态:处于就绪状态的线程被调用并获得处理器资源时,就进入运行状态,自动调用线程对象的run()方法。

4.阻塞状态:正在运行的线程,被人为挂起或执行一些耗时的输入输出操作时,让出CPU,并暂时中止自己的执行,进入阻塞状态。阻塞时不会进入线程队列排队,直到引起阻塞的事件消除后才进入就绪状态。

5.终止状态:线程调用stop()方法或run()方法结束后,处于死亡状态,不能再继续执行。

五、线程操作的相关方法

操作线程的主要方法在Thread类中:

1.取得和设置线程的名称

Thread类可以通过getName()取得线程的名称,通过setName()设置线程的名称。

线程的名称一般在启动线程前设置,也允许为已经运行的线程设置名称,如果没有设置名称,系统会为其自动分配名称,格式为Thread-X。

Java程序每次运行至少启动几个线程?

每当使用Java命令启动一个程序时,都会启动一个JVM,每一个JVM就是操作系统的一个进程,Java本身就具备了垃圾收集机制,所以在Java运行时至少开启两个线程,一个是main线程,一个是垃圾收集线程。

2.判断线程是否启动

isAlive():判断线程是否活着(已经启动且尚未运行结束)

主线程可能比其他线程先执行完,此时其他线程不会受影响,不会随着主线程的结束而结束。

3.线程的强制运行

在线程操作中,可以使用join()方法让一个线程强制运行,在哪个线程里调用join()方法,就阻塞哪个线程,直到被调用的线程执行结束,才继续执行原先的线程。

4.线程的休眠

当线程A正在运行时,另一个线程B可以通过调用线程A的interrupt()方法中断A的运行;

如果线程的休眠被中断,则被中断线程会抛出InterruptedException异常。

5.后台线程

在Java程序中,只要前台有一个线程在运行,则整个Java进程都不会消失,若设置一个后台线程,这样即使Java进程结束了,此后台线程仍然会继续执行,setDaemon()方法可将一个线程设为后台线程。

6.线程的优先级

所有的线程在运行前都保持在就绪状态,那么此时,哪个优先级高,哪个线程就有可能被调用。

通过setPriority()设置线程的优先级,通过getPriority()获取线程的优先级,线程的优先级的级别有以下三种:

class ThreadTask implements Runnable{	public void run() {		for(int i=0;i<5;i++){			try {				Thread.sleep(1000);			} catch (Exception e) {			}				System.out.println(Thread.currentThread().getName()+"-->"+i);		}	}}public class Main {	public static void main(String[] args){		Thread t1 = new Thread(new ThreadTask(),"threadA");		Thread t2 = new Thread(new ThreadTask(),"threadB");		Thread t3 = new Thread(new ThreadTask(),"threadC");		t1.setPriority(Thread.MAX_PRIORITY);		t2.setPriority(Thread.NORM_PRIORITY);		t3.setPriority(Thread.MIN_PRIORITY);		t1.start();		t2.start();		t3.start();			}}运行结果:

threadA-->0threadC-->0threadB-->0threadA-->1threadB-->1threadC-->1threadA-->2threadB-->2threadC-->2threadB-->3threadC-->3threadA-->3threadB-->4threadA-->4threadC-->4

线程会根据其优先级的大小来决定哪一个线程先运行,但并非是优先级高的就一定会先执行,哪个线程先执行最终由CPU的调度决定。

主线程的优先级是NORM_PRIORITY,通过getPriority()返回的值为5,是中等级别。

7.线程的礼让

线程yield()方法可以让暂停一个线程的操作,让给其他线程运行,但是暂停的时长是不确定的。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表