线程和进程的区别:
一、关于进程和线程,首先从定义上理解就有所不同
1、进程是什么? 是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是可以独 立运行的一段程序。
2、线程又是什么? 线程进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源。 在运行时,只是暂用一些计数器、寄存器和栈 。
二、他们之间的关系
1、一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程(通常说的主线程)。
2、资源分配给进程,同一进程的所有线程共享该进程的所有资源。
3、线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
4、处理机分给线程,即真正在处理机上运行的是线程。 5、线程是指进程内的一个执行单元,也是进程内的可调度实体。
三、从三个角度来剖析二者之间的区别
1、调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
2、并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。
3、拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源
线程是一组指令的集合。
多线程的创建方式:
1.继承Thread类
/**
*
* @ClassName: MyThread2
* @Description: TODO(通过继承Thread创建多线程)
* @author huasc
* @date 2017年8月29日 上午9:20:04
*
*/
public class MyThread2 extends Thread {
//重写run方法
@Override
public void run() {
for (int i = 0; i <10; i++) {
//输出线程名
System.out.println(this.getName()+i);
}
super.run();
}
}
2.实现Runable接口
/**
*
* @ClassName: MyThread
* @Description: TODO(通过实现Runnable接口创建多线程)
* @author huasc
* @date 2017年8月29日 上午9:16:42
*
*/
public class MyThread implements Runnable {
//重写run方法
@Override
public void run() {
for (int i = 0; i <10; i++) {
//输出线程名
System.out.println(Thread.currentThread().getName()+i);
}
}
}
3.直接在函数体中使用:
/**
*
* @ClassName: MyThread3
* @Description: TODO(直接在函数体中创建多线程)
* @author huasc
* @date 2017年8月29日 上午9:25:37
*
*/
public class MyThread3 {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <10; i++) {
//输出线程名
System.out.println(Thread.currentThread().getName()+i);
}
}
});
}
比较
实现Runnable接口优势:
1)适合多个相同的程序代码的线程去处理同一个资源
2)可以避免Java中的单继承的限制
3)增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。
继承Thread类优势:
1)可以将线程类抽象出来,当需要使用抽象工厂模式设计时。
2)多线程同步
在函数体使用优势
1)无需继承thread或者实现Runnable,缩小作用域。
线程的启动:
public class MyThreadTest {
public static void main(String[] args) {
//继承Thread类的启动方式
new MyThread2().start();
new MyThread2().start();
new MyThread2().start();
//实现Runnable接口启动方式
MyThread m = new MyThread();
new Thread(m, "线程1:").start();
new Thread(m, "线程2:").start();
new Thread(m, "线程3:").start();
}
}
线程的启动实际上是调用start();方法而不是调用run();
run():
方法是线程的执行体,线程并不会并发执行,而是后一个线程等待前一个线程执行结束再执行,相当于传统的方法调用。
start():
方法会使线程同步执行,互相争夺CPU资源,抢到CPU执行权的会被执行,没有抢到的继续等待。
线程的五种状态:
1、新建状态:线程对象已经创建,还没有在其上调用start()方法。
2、就绪状态:当线程有资格运行,但调度程序还没有把它选定为运行线程时线程所处的状态。当start()方法调用时,线程首先进入可运行状态。在线程运行之后或者从阻塞、等待或睡眠状态回来后,也返回到可运行状态。
3、运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。
4、等待/阻塞/睡眠状态:这是线程有资格运行时它所处的状态。实际上这个三状态组合为一种,其共同点是:线程仍旧是活的,但是当前没有条件运行。换句话说,它是可运行的,但是如果某件事件出现,他可能返回到可运行状态。
5、死亡状态:当线程的run()方法完成时就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。