进程和线程的区别

//TODO linux用户态和内核态是如何进行转换,为什么要转换,什么是系统中断,它的内核态的多线程是如何通过轻量级线程方式实现

线程和进程的由来

线程和进程的区别

进程是资源分配的最小单位,线程是CPU调度的最小单位

  • 所有进程相关资源都被记录在PCB(进程控制块)中

  • 进程是抢占处理机的调度单位;线程属于某个进程,共享其资源
  • 线程只由堆栈寄存器,程序计数器和线程控制块TCB组成

总结

java进程和线程的关系

一个程序是一个可执行的文件,一个进程是一个执行中的程序的实例.jvm是多线程的,如垃圾收集器的线程

线程的start和run方法的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

public class ThreadTest {
private static void attack() {
System.out.println("fight");
System.out.println("current thread is:" + Thread.currentThread().getName());
}

public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
attack();
}
};
System.out.println("current main thread is:" + Thread.currentThread().getName());
// t.run();//main
t.start();//thread-0
}
  • run方法只是Thread的一个普通方法的调用,还是在主线程里执行

  • 调用start方法会创建一个新的子线程

Thread和Runnable是什么关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class ThreadDemo {
public static void main(String[] args) {
MyThread mt1 = new MyThread("thread1");
MyThread mt2 = new MyThread("thread2");
MyThread mt3 = new MyThread("thread3");
mt1.start();
mt2.start();
mt3.start();
}
}

public class MyThread extends Thread {
private String name;

public MyThread(String name) {
this.name = name;
}

@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Thread start:" + this.name + ",i=" + i);
}
}
}
//输出是交替执行的,说明是多线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class RunnableDemo {
public static void main(String[] args) {
MyRunnable mr1 = new MyRunnable("runnable1");
MyRunnable mr2 = new MyRunnable("runnable2");
MyRunnable mr3 = new MyRunnable("runnable3");
Thread t1 = new Thread(mr1);
Thread t2 = new Thread(mr2);
Thread t3 = new Thread(mr3);
t1.start();
t2.start();
t3.start();
}
}

public class MyRunnable implements Runnable {
private String name;

public MyRunnable(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Thread start:" + this.name + ",i=" + i);
}
}
}
//输出是交替执行的,说明是多线程
  • Thread是一个实现了Runnable的类,使得run支持多线程
  • 因类的单一继承原则,推荐使用Runnable接口

如何给run()方法传参

如何实现处理线程的返回值(主线程等待,join,callable,线程池)

  • 1.主线程等待
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class CycleWait implements Runnable {
private String val;

@Override
public void run() {
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
val = "we have data now";

}

public static void main(String[] args) throws InterruptedException {
CycleWait cw = new CycleWait();
Thread t = new Thread(cw);
t.start();
while (cw.val == null) {
Thread.currentThread().sleep(100);
}

//t.join();
System.out.println(cw.val);
}
}
  • 2.使用Thread类的join()阻塞当前线程以等待子线程处理完毕(无法更精细)

缺点:无法更精细,如上例中多个Runnable,无法做到当Runnable1的i=5 再执行Runnable2

  • 3.通过Callable借口实现:通过FutureTask Or 线程池获取
1
2
3
4
5
6
7
8
9
10
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
String val = "test";
System.out.println("ready to work");
Thread.currentThread().sleep(4000);
System.out.println("Work is done");
return val;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
方式1:通过FutureTask
public class FutureTaskDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
new Thread(futureTask).start();
if (!futureTask.isDone()) {
System.out.println("Please wait");
}
System.out.println("Task return:" + futureTask.get());
}
}

输出:
Please wait
ready to work
Work is done
Task return:test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
方式二:通过线程池

public class ThreadPoolDemo {

public static void main(String[] args) {
ExecutorService newCachethreadPool = Executors.newCachedThreadPool();
Future<String> future = newCachethreadPool.submit(new MyCallable());

if (!future.isDone()) {
System.out.println("Please wait");
}
try {
System.out.println("Task return:" + future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
newCachethreadPool.shutdown();
}
}
}

进程状态

  • 1.新建(New):创建后尚未启动
  • 2.运行(Runnable):包含Running和Ready,可能正在执行,也可能在等待cpu分配时间
  • 3.无限期等待(Waiting):不会被分配cpu执行时间,需要被显示唤醒

  • 4.限期等待(Timed Waiting):在一定时间后会由系统自动唤醒

  • 5.阻塞(Blocked):等待获取排他锁
  • 6.结束(Terminated):已终止线程的状体,线程已经结束执行

sleep和wait的区别

基本的差别

  • sleep是Thread的方法,而wait是Object的方法
  • sleep方法可以在任何地方使用;wait只能在synchronize方法或者synchronized块中使用(获取锁才能释放锁)

最主要区别

  • Thread.sleep会让出cpu,不会让出锁
  • Object.wait会让出cpu,还会让出锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class WaitSleepDemo {
public static void main(String[] args) {
final Object lock = new Object();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread A wait for lock");
synchronized (lock) {
try {
System.out.println("Thread A get lock");
Thread.sleep(20);
System.out.println("Thread A do wait method");
lock.wait(1000);
System.out.println("Thread a is done");
} catch (InterruptedException e) {
e.printStackTrace();
}

}

}
}).start();

//保证前一个线程先执行
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}

new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread B wait for lock");
synchronized (lock) {
try {
System.out.println("Thread B get lock");
System.out.println("Thread B is sleeping");
Thread.sleep(10);
System.out.println("Thread B is done");
} catch (InterruptedException e) {
e.printStackTrace();
}

}

}
}).start();
}
}

输出:
Thread A wait for lock
Thread A get lock
Thread B wait for lock
Thread A do wait method
Thread B get lock
Thread B is sleeping
Thread B is done
Thread A is done

notify和notifyall的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

public class WaitSleepDemo {
public static void main(String[] args) {
final Object lock = new Object();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread A wait for lock");
synchronized (lock) {
try {
System.out.println("Thread A get lock");
Thread.sleep(20);
System.out.println("Thread A do wait method");
lock.wait();
System.out.println("Thread A is done");
} catch (InterruptedException e) {
e.printStackTrace();
}

}

}
}).start();

try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}

new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread B wait for lock");
synchronized (lock) {
try {
System.out.println("Thread B get lock");
System.out.println("Thread B is sleeping");
Thread.sleep(10);
System.out.println("Thread B is done");
lock.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}

}

}
}).start();
}
}
输出:
Thread A wait for lock
Thread A get lock
Thread B wait for lock
Thread A do wait method
Thread B get lock
Thread B is sleeping
Thread B is done //notify通知A
Thread A is done

两个概念

  • 锁池EntryList

  • 等待池WaitSet

区别

yeild

当调用yeild方法时,会暗示线程调度器当前线程愿意让出cpu,但是线程调度器有可能会忽略这个暗示

yeild对锁不会有影响

如何中断线程

已经被抛弃的方法

目前使用的方法

调用interupt(),通知线程应该中断了

  • 1.如果线程处于被阻塞的状态(如sleep,wait,join),那么线程将立刻退出被阻塞的状态,并且抛出一个InterruptedException异常
  • 2.如果线程处于活动状态,那么将该线程的中断标志设置为true.被设置中断标志的线程将继续正常运行,不受影响
  • 3.需要调用线程配合中断:经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程;在调用阻塞方法的时候,捕获InterruptedException
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

public class InterruptDemo {
public static void main(String[] args) throws InterruptedException {
Runnable interruptTask = new Runnable() {
@Override
public void run() {
int i = 0;
try {
//在正常运行任务时,经常检查本线程的中断标志位,如果被设置了中断标志就自行停止线程
while (!Thread.currentThread().isInterrupted()) {
Thread.sleep(100); // 休眠100ms
i++;
System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().getState() + ") loop " + i);
}
} catch (InterruptedException e) {
//在调用阻塞方法时正确处理InterruptedException异常。(例如,catch异常后就结束线程。)
System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().getState() + ") catch InterruptedException.");
}
}
};
Thread t1 = new Thread(interruptTask, "t1");
System.out.println(t1.getName() +" ("+t1.getState()+") is new.");

t1.start(); // 启动“线程t1”
System.out.println(t1.getName() +" ("+t1.getState()+") is started.");

// 主线程休眠300ms,然后主线程给t1发“中断”指令。
Thread.sleep(300);
t1.interrupt();
System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");

// 主线程休眠300ms,然后查看t1的状态。
Thread.sleep(300);
System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");
}
}
1
2
3
4
5
6
7
t1 (NEW) is new.
t1 (RUNNABLE) is started.
t1 (RUNNABLE) loop 1
t1 (RUNNABLE) loop 2
t1 (TIMED_WAITING) is interrupted.
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.

线程状态及状态之间的转换

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×