第一种实现线程的方式:继承Thread
publicclass NumberThread extends Thread{
privateint first;
publicintgetFirst() {
returnfirst;
}
publicvoid setFirst(intfirst) {
this.first =first;
}
public NumberThread(Stringname,intfirst) {
super(name);
this.first =first;
}
public void run() {
System.out.println(this.getName()+":");
for(inti=first;i<100;i=i+2){
System.out.print(i+"");
}
System.out.println(this.getName()+"结束!!");
}
publicstatic voidmain(String[]args){
System.out.println("currentThread="+Thread.currentThread().getName());
NumberThread thread_odd=newNumberThread("奇数线程", 1);
NumberThread thread_even=newNumberThread("偶数线程", 2);
thread_odd.start();
thread_even.start();
System.out.println("activeCount "+Thread.currentThread().activeCount());
}
}
第一种方式运行结果:
currentThread=main
奇数线程:
activeCount 3
1 3 5 7 偶数线程:
9 2 11 13 15 4 17 619 8 21 10 23 12 25 14 27 16 29 18 31 20 33 22 35 24 37 26 39 28 30 32 34 36 3840 42 41 44 43 45 46 48 50 47 52 54 56 58 60 62 64 66 68 70 49 72 51 74 53 7655 78 57 80 59 61 63 82 65 84 67 86 69 88 71 90 73 92 75 94 77 96 79 98 81 偶数线程 结束!!
83 85 87 89 91 93 9597 99 奇数线程 结束!!
程序说明如下:
(1)一个运行java程序的进程,默认首先启动main线程。在main方法中创建和启动两个线程。
(2)Main线程先于其他线程执行。线程启动后处于就绪状态,等待操作系统调度执行。线程执行次序以及是否被打断不有程序控制。
第二种实现线程的方式:实现Rnnable接口
public classNumberRunnable implements Runnable{
private int first;
public NumberRunnable(intfirst){
this.first=first;
}
public void run() {
System.out.println(Thread.currentThread().getName()+":");
for(inti=first;i<100;i=i+2){
System.out.print(i+"");
}
System.out.println(Thread.currentThread().getName()+"结束!!");
}
public static voidmain(String args[]){
NumberRunnable odd=newNumberRunnable(1);
NumberRunnable even=newNumberRunnable(2);
Thread thread_odd=new Thread(odd,"奇数线程");
Thread Thread_even=new Thread(even,"偶数线程");
thread_odd.start();
Thread_even.start();
}
}
第二种方式运行结果:
奇数线程:
1 3 5 7 9 11 13 偶数线程:
2 4 6 8 10 12 14 1618 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 6870 72 74 76 78 80 82 84 86 88 90 92 94 96 98 偶数线程 结束!!
15 17 19 21 23 25 2729 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 7981 83 85 87 89 91 93 95 97 99 奇数线程 结束!!
7.3线程的同步机制
1.如果并发执行的多个线程间需要共享资源或者交换数据,则这一组线程成为交互线程
2.交互线程之间存在两种关系:竞争和协作。对于竞争关系的交互线程间需要采用线程同步的方式解决共享资源的问题,有临界区和对象锁的概念。对于协作关系的交互线程间需要采用线程同步的方式解决线程间执行速度不一致的问题,有信号量的概念,pv操作。P操作是指测试信号量状态的操作,v操作是指改变信号量状态的操作。
3.线程互斥是解决线程间竞争关系的手段。线程互斥是指若干个线程使用同一个共享资源的时候,任何时候最多允许一个线程去使用,其他线程必须等待该线程释放该资源。
4.对于同一个对象,在任何时刻都只能有一个线程执行临界区语句,对该对象进行操作,其他竞争使用该对象的线程必须等待,直到对象锁被释放。互斥锁锁定的是对象和其操作。
线程互斥案例:斥锁锁定的是对象和其操作。
public class Account {
private String name;
private double balance;
public Account(String name) {
this.name = name;
this.balance = 0;
}
public String getName() {
return this.name;
}
public double balance() {
return this.balance;
}
public void put(double value) {
if (value > 0) {
this.balance += value;
}
}
public double get(double value) {
if (value > 0) {
if (value <=this.balance) {
this.balance -= value;
} else {
value = this.balance;
this.balance = 0;
}
return value;
}
return 0;
}
}
public class Save extends Thread {
private Account account;
private double value;
public Save(Account a1, double value) {
this.account = a1;
this.value = value;
}
public synchronized void run() {
synchronized (this.account) {
double howMuch = this.account.balance();
try {
sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.account.put(value);
System.out.println(this.account.getName() + "账户:现有" + howMuch + "存入" + this.value + ",余额"
+ this.account.balance());
}
}
}
}
public class Fetch extends Thread {
private Account account;
private double value;
public Fetch(Account a1, double value) {
this.account = a1;
this.value = value;
}
public void run() {
synchronized (this.account) {
double howMuch = this.account.balance();
try {
sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println(this.account.getName() + "账户:现有" + howMuch +
"取走" + this.account.get(this.value) + ",余额"
+ this.account.balance());
}
}
}
public static void main(String[] args) throws Exception {
Account wang = new Account("Wang");
Save save1=new Save(wang,100);
save1.start();
save1.join();
Save save2=new Save(wang, 200);
save2.start();
save2.join();
Fetch fetch=new Fetch(wang, 300);
fetch.start();
fetch.join();
}
}
运行结果:
Wang账户:现有0.0存入100.0,余额100.0
Wang账户:现有100.0存入200.0,余额300.0
Wang账户:现有300.0取走300.0,余额0.0
线程同步案例
public class BufferLock {
private int value;
private boolean isEmpty=true;
public synchronized void put(int i){
while(!isEmpty){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
value=i;
isEmpty=false;
notify();
}
public synchronized int get(){
while(isEmpty){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
isEmpty=true;
this.notify();
return value;
}
}
public class Sender extends Thread{
private BufferLock buffer;
public Sender(BufferLock buffer){
this.buffer=buffer;
}
public void run(){
for(int i=0;i<5;i++){
buffer.put(i);
System.out.println("Sender put :"+i);
}
}
}
public class Receiver extends Thread {
private BufferLock buffer;
public Receiver(BufferLock buffer) {
this.buffer = buffer;
}
public void run(){
for(int i=0;i<5;i++){
System.out.println("\t\t\tReceiver get : "+buffer.get());
}
}
public static void main(String args[]) throws Exception{
BufferLock buffer=new BufferLock();
Sender send=new Sender(buffer);
send.start();
Receiver rec=new Receiver(buffer);
rec.start();
}
}
运行结果
Sender put :0
Receiver get : 0
Sender put :1
Receiver get : 1
Sender put :2
Sender put :3
(还有问题需要调一下)
Receiver get : 2
Receiver get : 3
Sender put :4
Receiver get : 4