java多线程

java多线程

Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

线程生命周期

1.新建状态(New):新创建了一个线程对象。
2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3.运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4.阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

4.1 等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
4.2 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
4.3 其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5.死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

线程的优先级

每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。
Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。
具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。

创建线程

通过实现 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
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
package com.thread;
/**
* 输出ABCABCABCABCABCABCABCABCABCABC
* @author ming
*
*/
class RunnableDemo implements Runnable{
private String name;
private Object prev;
private Object self;

private RunnableDemo(String name, Object prev, Object self) {
this.name = name;
this.prev = prev;
this.self = self;
}

@Override
public void run() {
int count = 10;
while (count > 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
count--;

self.notify();
}
try {
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
}
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
RunnableDemo pa = new RunnableDemo("A", c, a);
RunnableDemo pb = new RunnableDemo("B", a, b);
RunnableDemo pc = new RunnableDemo("C", b, c);

new Thread(pa).start();
Thread.sleep(100);
new Thread(pb).start();
Thread.sleep(100);
new Thread(pc).start();
Thread.sleep(100);
}
}

通过继承 Thread类本身

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
package com.thread;
class Thread1 extends Thread{
private String name;
public Thread1(String name) {
this.name = name;
}
public void run() {
for(int i=0; i<5; i++) {
System.out.println(name+i);
try {
sleep((int)Math.random()*10);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ExtendsTreadDemo {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"主线程运行开始!");
Thread1 thread1 = new Thread1("A");
Thread1 thread2 = new Thread1("B");
thread1.start();
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start();
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ "主线程运行结束!");
}
}

通过 Callable和 Future创建线程

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
package com.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableThreadDemo implements Callable<Integer> {
public static void main(String[] args)
{
CallableThreadDemo ctt = new CallableThreadDemo();
FutureTask<Integer> ft = new FutureTask<>(ctt);
for(int i = 0;i < 10;i++)
{
System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);
if(i==5)
{
new Thread(ft,"有返回值的线程").start();
}
}
try
{
System.out.println("子线程的返回值:"+ft.get());
} catch (InterruptedException e)
{
e.printStackTrace();
} catch (ExecutionException e)
{
e.printStackTrace();
}

}
@Override
public Integer call() throws Exception
{
int i = 0;
for(;i<10;i++)
{
System.out.println(Thread.currentThread().getName()+"call:"+i);
}
return i;
}
}

同步代码块与同步方法

这两个方法用的是一把锁,同步方法直接在方法上加synchronized实现加锁,同步代码块则在方法内部加锁,很明显,同步方法锁的范围比较大,而同步代码块范围要小点,一般同步的范围越大,性能就越差,一般需要加锁进行同步的时候,肯定是范围越小越好,这样性能更好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.thread;
public class SynchronizedDemo {
public synchronized void test1() {
for(int i= 0;i<5 ; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}

public void test2() {
synchronized (this) {
for(int i= 0;i<5 ; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}

public static void main(String[] args) {
SynchronizedDemo sd = new SynchronizedDemo();
Thread t1 = new Thread(new Runnable() {public void run() {sd.test1();}});
Thread t2 = new Thread(new Runnable() {public void run() {sd.test2();}});
t1.start();
t2.start();
}
}

本文标题:java多线程

文章作者:wangming

发布时间:2019年01月21日 - 17:59:01

最后更新:2019年01月22日 - 23:35:35

原始链接:https://syxiaowanzi.github.io/2019/01/21/java多线程/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%