实现线程的方式是一,继承Thread类,重写父类的run()方法
二,实现接口Runnable中的run()方法。
下面是简单的例子
例子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
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
package
com.direct.demo;
public
class
Bank {
private
static
int
money;
public
int
getMoney(){
return
money;
}
public
void
saveMoney(
int
m){
synchronized
(
this
) {
System.out.println(
"存钱后的总金额:"
+(money+=m));
}
}
public
void
drawMoney(
int
m){
synchronized
(
this
) {
Bank bank =
new
Bank();
if
(bank.getMoney()<=
0
) {
System.out.println(
"没得钱,取个pi"
);
}
else
{
System.out.println(
"取钱后剩的总金额:"
+(money-=m));
}
}
}
public
static
void
main(String[] args) {
Man m1 =
new
Man();
Women w =
new
Women();
Thread t1 =
new
Thread(m1);
Thread t2 =
new
Thread(m1);
Thread t3 =
new
Thread(m1);
Thread t4 =
new
Thread(w);
Thread t5 =
new
Thread(w);
Thread t6 =
new
Thread(w);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
class
Man
implements
Runnable{
private
Bank bank =
new
Bank();
public
void
run() {
int
m =
100
;
int
i=
0
;
while
(i<
5
) {
bank.saveMoney(m);
i++;
try
{
Thread.sleep(
100
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
}
}
class
Women
implements
Runnable{
private
Bank bank =
new
Bank();
public
void
run() {
int
m =
100
;
int
i=
0
;
//bank.getMoney()>0
while
(i<
5
) {
bank.drawMoney(m);
try
{
Thread.sleep(
100
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
}
|
例子2:生产者与消费者问题
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
package
com.direct.demo;
public
class
Clerk {
private
int
product = -
1
;
//这个方法由生产者调用
public
synchronized
void
setProduct(
int
product){
if
(
this
.product != -
1
) {
try
{
wait();
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
this
.product = product;
System.out.printf(
"生产者设定 (%d)%n"
,
this
.product);
notify();
}
//这个方法由消费者调用
public
synchronized
int
getProduct(){
if
(
this
.product==-
1
) {
try
{
wait();
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
int
p =
this
.product;
System.out.printf(
"消费者取走 (%d)%n"
,
this
.product);
this
.product = -
1
;
notify();
return
p;
}
public
static
void
main(String[] args) {
Clerk clerk =
new
Clerk();
new
Thread(
new
ProducerInt(clerk)).start();
new
Thread(
new
ConsumerInt(clerk)).start();
}
}
class
ProducerInt
implements
Runnable{
private
Clerk clerk;
public
ProducerInt(Clerk clerk){
this
.clerk = clerk;
}
public
void
run() {
System.out.println(
"生产者开始生产整数了.................."
);
for
(
int
product =
1
; product <=
10
; product++) {
try
{
Thread.sleep((
int
)Math.random()*
300
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
clerk.setProduct(product);
}
}
}
class
ConsumerInt
implements
Runnable{
private
Clerk clerk;
public
ConsumerInt(Clerk clerk){
this
.clerk = clerk;
}
public
void
run() {
System.out.println(
"消费者开始消耗整数........"
);
for
(
int
i =
1
; i <=
10
; i++) {
try
{
Thread.sleep((
int
)Math.random()*
300
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
clerk.getProduct();
//从店员取走整数
}
}
}
|
例子3:购票窗口实现票数同步
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
|
package
com.direct.demo;
import
java.util.concurrent.locks.Lock;
import
java.util.concurrent.locks.ReentrantLock;
public
class
ThreadTicket {
public
static
void
main(String[] args) {
Booking b1 =
new
Booking(
"军人售票口"
);
Booking b2 =
new
Booking(
"学生售票口"
);
Booking b3 =
new
Booking(
"老年人售票口"
);
Booking b4 =
new
Booking(
"网上售票口"
);
b1.start();
b2.start();
b3.start();
b4.start();
}
}
/*
* 多窗口卖票系统。多线程
* 票数为静态的,共享数据
* synchronized(对象){}代码块中的内容是加锁的,
* 即当一个线程在使用时,其他线程不可以进入。
* 使得共享资源数据的安全。
*/
class
Booking
extends
Thread{
public
Booking(String name){
super
(name);
}
static
int
ticket =
50
;
//票数共50张
Lock lock =
new
ReentrantLock();
//明锁
|
/*
* ReentrantLock根据传入构造方法的布尔型参数实例化出Sync的实现类FairSync和NonfairSync
* ,分别表示公平的Sync和非公平的Sync。
* 由于ReentrantLock我们用的比较多的是非公平锁
ReentrantLock 和synchronized 均为重入锁
* 1. ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。
2. ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。
3. ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。
对ReentrantLock的可重入锁这篇博客使用简单的例子进行讲解, http://blog.csdn.net/yanyan19880509/article/details/52345422
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
|
* Lock是个接口,只能实例化它的子类
* 明锁适合高并发,上万
* 暗锁适合并发率不高时,效率高
*/
//重写run方法,
public
void
run(){
while
(ticket>
0
){
synchronized
(Booking.
class
) {
if
(ticket>
0
) {
System.out.println(
super
.getName()+
"窗口---->卖出的车票号No."
+ticket);
ticket--;
}
else
{
System.out.println(
super
.getName()+
"票已售罄!!!"
);
}
try
{
sleep(
100
);
//睡100毫秒,抛出多线程异常
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
/*lock.lock();//加锁,锁定以下代码
if (ticket>0) {
System.out.println(super.getName()+"卖票:"+ticket);
ticket--;
}else {
System.out.println(super.getName()+"票已售罄!!!");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.unlock();//解锁
*/
}
}
}
|
例子4:线程中sleep()和wait()方法测试
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
|
package
com.direct.demo;
public
class
TestSleepaWait {
public
static
void
main(String[] args) {
new
Thread(
new
Thread1()).start();
try
{
Thread.sleep(
5000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
new
Thread(
new
Thread2()).start();
}
}
class
Thread1
implements
Runnable{
public
void
run() {
synchronized
(TestSleepaWait.
class
) {
System.out.println(
"Thread1 is start........"
);
System.out.println(
"Thread1 is wait.............."
);
try
{
//调用wait方法,线程会放弃对象锁,进入等待对象的等待锁定池
TestSleepaWait.
class
.wait();
}
catch
(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"Thread1 is go on........"
);
System.out.println(
"Thread1 is over!"
);
}
}
}
class
Thread2
implements
Runnable{
@Override
public
void
run() {
synchronized
(TestSleepaWait.
class
) {
System.out.println(
"Thread2 is enter.........."
);
System.out.println(
"Thread2 is sleep......."
);
//只有针对对象调用notify()方法后本线程才进入对象锁定池
//准备获取对象进入运行状态
TestSleepaWait.
class
.notify();
//===============
//如果把上句注释掉。即对象锁调用了wait方法,但是没有调用notify
//程序就一致处于挂起状态
try
{
Thread.sleep(
5000
);
//sleep方法暂停执行时间,让出CPU,监控状态保持,
//时间到 了就回复运行, 不会释放对象锁
}
catch
(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"Thread2 is going on.........."
);
System.out.println(
"Thread2 is over!!!!"
);
}
}
}
|
例子5:sleep()实现对象存取值
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
61
62
63
64
65
|
package
com.direct.demo;
public
class
ThreadCom {
public
static
void
main(String[] args) {
Person person =
new
Person();
new
Thread(
new
Producer(person)).start();
new
Thread(
new
Consumer(person)).start();
}
}
class
Person{
private
String name =
"张杰"
;
private
String sex =
"男"
;
public
synchronized
void
put(String name,String sex){
this
.name = name;
this
.sex = sex;
try
{
Thread.sleep(
100
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
//方法加锁
public
synchronized
void
get(){
System.out.println(name+
"----->"
+sex);
try
{
Thread.sleep(
100
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
}
class
Consumer
implements
Runnable{
Person person;
public
Consumer(Person person){
this
.person = person;
}
public
void
run() {
while
(
true
){
person.get();
}
}
}
class
Producer
implements
Runnable{
Person person;
public
Producer(Person person){
this
.person = person;
}
public
void
run() {
int
i =
0
;
while
(
true
) {
if
(i==
0
) {
person.put(
"谢娜"
,
"女"
);
}
else
{
person.put(
"张杰"
,
"男"
);
}
i = (i+
1
)%
2
;
//奇数和偶数
}
}
}
|
例子6:死锁发生条件
在写代码时要避免死锁
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
61
62
63
64
|
package
com.direct.demo;
public
class
DeadLock {
public
static
void
main(String[] args) {
ThreadLock tl =
new
ThreadLock(
true
);
ThreadLock tl2 =
new
ThreadLock(
false
);
new
Thread(tl).start();
new
Thread(tl2).start();
}
}
/*
* 死锁的产生条件:
* 1、至少一个资源共享
* 2、至少有一个线程(任务),必须持有资源,且等待获取别的线程持有的资源
* 3、任务抢不到资源
* 4、必须有无限循环
* (1) 互斥条件:一个资源每次只能被一个进程使用。
* (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
* (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
* (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
* 举例说明:不可剥夺资源A、B,进程C、D
* 不可剥夺资源:一个进程申请了之后,不能强制收回,只能进程结束之后自动释放。内存是可剥夺资源
* 进程C申请了资源A,进程D申请了资源B。
* 接下来进程C的操作需要用到资源B,进程D的操作需要用到资源A
* 但是C、D都得不到资源,就引发了死锁
*/
class
Lock{
static
Object lockOne =
new
Object();
//资源A
static
Object lockTwo =
new
Object();
//资源B
}
class
ThreadLock
implements
Runnable{
private
boolean
flag;
public
ThreadLock(
boolean
flag){
this
.flag = flag;
}
@Override
public
void
run() {
if
(flag){
while
(
true
) {
synchronized
(Lock.lockOne) {
System.out.println(
" this is lockOne"
);
synchronized
(Lock.lockTwo) {
System.out.println(
"this is lockTwo"
);
}
}
}
}
else
{
while
(
true
) {
synchronized
(Lock.lockTwo) {
System.out.println(
" 这是 lockTwo"
);
synchronized
(Lock.lockOne) {
System.out.println(
"这是 lockOne"
);
}
}
}
}
}
}
|