一、进程:
1. 进程概念:
程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。而进程是程序在处理机上的一次执行过程,他是一个动态的概念。
进程是一个具有独立功能的程序,一个实体,每一个进程都有它自己的地址空间。
2. 进程的状态:
进程执行时的间断性,决定了进程可能具有多种状态。
1) 就绪状态(Ready)
2) 运行状态(Running)
3) 阻塞状态(Blocked)
二、线程:
1. 线程的概念:
线程实际上是在进程的基础之上的进一步划分,一个进程启动后,里面的若干个程序由可以划分成若干个线程。线程:是进程的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行,一个进程最少有一个线程,这个情况叫单线程程序。
并行:两个任务同时运行(多个CPU)
并发:两个任务同时请求运行,而处理器一次性只能接受一个任务,就会把两个任务安排轮流执行,由于CPU时间片运行较短就会感觉在一起执行。
三、线程的基本使用:
在JAVA中如果要实现多线程的操作,有两种实现方法:
1. 继承Thread类:
public class ThreadDemo {
public static void main(String[] args) {
new MyThread().start();//启动线程
}
}
// 继承实现线程
class MyThread extends Thread{
@Override
public void run() {
super.run();
for (int i = 0; i < 50 ; i++) {
System.out.println("当前执行:"+i);
}
}
}
2. 实现Runnable接口:
public class ThreadDemo {
public static void main(String[] args) {
new Thread(new MyRunnableThread()).start();//启动线程
// 启动实现Runnable的第二种方式
new MyRunnableThread().run();
}
}
class MyRunnableThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50 ; i++) {
System.out.println("当前执行:"+i);
}
}
}
一般推荐使用第二种实现接口的方法,第一种继承是创建一个线程,第二种是创建一个线程的执行方法,使用的是实现方法,所以还可以继承其他的类,可扩展性较强。
四、线程的休眠:
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
上面是Thread中的一个方法,这个方法使当前正在执行的线程以指定的毫秒数暂停,释放CPU的时间片,具体取决于系统定时器和调度程序的精度和准确性。线程不会丢失任何显示器的所有权。
传递参数:millis 以毫秒为单位,nanos 纳秒。方法加入参数二纳秒,可以使时间更精确。
异常:InterruptedException 如果任何线程中断当前线程。则抛出异常,同时清除当前线程的中断状态。IllegalArgumentException 纳秒超出999999范围或者毫秒为负数。
// 继承实现线程
class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 50 ; i++) {
try {
Thread.sleep(1000);
//使用纳秒和可精确
//Thread.sleep(10000,1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("当前执行:"+i);
}
}
}
五、JOIN与中断线程:
1. JOIN:
public final synchronized void join(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
join(millis);
}
等待这个线程死亡。通俗的说就是那个线程调用了他,就直接到这个线程方法执行完为止。
参数异同和上面sleep一样。
public class ThreadDemo {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnableThread());thread.start();
for (int i = 0; i < 50 ; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程当前执行:"+i);
// 当主线程执行到20时,任务线程进行JOIN
if (i == 20){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class MyRunnableThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50 ; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("MyRunnableThread当前执行:"+i);
}
}
}
效果:
如图可知,就是让调用的任务线程执行完毕,再执行主线程。如果未加入JOIN,共同进行执行(谁抢到就先执行谁)。
2. 中断(Interrupt):
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
return isInterrupted(false);
}
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
interrupt() 方法中断这个线程,除非当前线程中断自身,这是始终允许的。
isInterrupted() 测试当前线程是否中断,该方法可以清除线程的中断状态。通俗的说,如果这个方法被两次调用,那么第二次调用则会返回false,除非当前线程再次中断,在第一个调用已经清除其中断状态之后,第二个调用之前已经经过检查。忽略线程中断,因为线程在中断时不存在将该方法返回false。
public class ThreadDemo {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnableThread());thread.start();
for (int i = 0; i < 50 ; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程当前执行:"+i);
// 当主线程执行到20时,任务线程进行JOIN
if (i == 20){
thread.interrupt();
}
}
}
}
class MyRunnableThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50 ; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("MyRunnableThread当前执行:"+i);
}
}
}
抛出了异常,sleep 中断了。做了一个中断的状态。真正中断得现场自己来中断。如果想要它真正中断,得用如下方法:
public class ThreadDemo {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnableThread());thread.start();
for (int i = 0; i < 50 ; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程当前执行:"+i);
// 当主线程执行到20时,任务线程进行JOIN
if (i == 20){
thread.interrupt();
}
}
}
}
class MyRunnableThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50 ; i++) {
if (Thread.interrupted()){
break;// 如果处于中断状态,则break
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();// 中断当前线程
}
System.out.println("MyRunnableThread当前执行:"+i);
}
}
}
中断状态被捕捉后,中断线程。
原本想把线程的知识点写在一篇文章里,发现文章写的太长了,不方便阅读,所以将分为基础篇和进阶篇,进阶篇将会根据源码介绍 守护线程的优先级、线程同步、线程死锁、生产者与消费者的概念。