java多线程设计——线程启动,互斥,Single Threaded Execution

1.线程的启动

顺序,并发,并行

顺序:用于表示多个操作“依次处理”。比如把十个操作交给一个人处理,这个人就得一个一个地按顺序来处理

并行:用于表示多个操作“同时处理”。比如把十个操作交给两个人处理,这两个人就会并行处理。

并发:将操作打散成多个步骤,然后依次执行,就像是说一个人同时做好几件事,但是

他执行的动作是先做这件事,然后停下来再做另一件事。

 

实际上运行的线程就像上面这样在不断切换,顺序执行并发处理。

程序的终止:

Java程序的终止是指除守护线程以外的线程全部终止。守护线程是执行后台作业的线程。通过setDaemon()设置守护线程。

线程的启动1Thread类继承

扫描二维码关注公众号,回复: 913676 查看本文章

public class PrintThread extends Thread{

private String msg;

public PrintThread(String msg) {

super();

this.msg = msg;

}

public void run(){

for (int i = 0; i < 10000; i++) {

System.out.println(msg);

}

}

public static void main(String[] args) {

new PrintThread("God!").start();

new PrintThread("Nice!").start();

}

}

线程的启动2Runnable接口实现

public class Printer implements Runnable {

private String msg;

public Printer(String msg) {

super();

this.msg = msg;

}

@Override

public void run() {

// TODO Auto-generated method stub

for (int i = 0; i < 10000; i++) {

System.out.println(msg);

}

}

public static void main(String[] args) {

new Thread(new Printer("Good!")).start();

new Thread(new Printer("bad!")).start();

ThreadFactory factory = Executors.defaultThreadFactory();

factory.newThread(new Printer("XSM")).start();

}

}

利用ThreadFactory启动线程:

ThreadFactory factory = Executors.defaultThreadFactory();

factory.newThread(new Printer("XSM")).start();

线程的暂停:

Thread.sleep(1000);//暂停1s

2. 线程的互斥处理

多线程程序中的各个线程是自由运行的,所以他们有时会操作同一个案例

Synchronized方法处理互斥问题

Synchronized每次只能由一个线程执行,线程运行完synchornized方法后,释放锁

 

锁和监视:

获取锁有时叫做“拥有监视”或者“持有锁”

当前线程是否已获取某一对象的锁通过Thread.holdsLock方法确认,当前线程已获取对象obj的锁时,可使用assert来表示:

Assert Thread.holdsLock(obj);

每个实例都有独立的锁;如图bank1,bank2

 

synchronized代码块

Synchronized(表达式){

}

synchronized实例方法和synchronized代码块

Sychronzied void method(){

}

等效于

void method(){

Synchronized(this){

}

}

synchronized静态方法和synchronized代码块

 

synchronized静态方法是使用该类对象的锁来执行线程的互斥处理的,Somthing.classSomething类对应的java.lang.class类的实例

线程协作:

假如需要执行更精确的控制,而不是单纯的等待其他线程运行终止

例如:

如果空间为空则写入数据,如果非空则一直等待到变空为止

空间已为空时,“通知”正在等待的线程

wait方法:将线程放入 等待队列

如果要执行wait方法 ,线程必须持有锁,如图:

 

当线程A进入等待队列的时候,会释放锁,这个时候线程B就会获取到


notify方法---从等待队列中取出线程

notify 方法会将等待队列中的一个线程取出。如图

 

线程A退出等待队列,想要进入wait的下一个操作,但刚才执行notify的线程B仍痴有锁

刚才执行notify的线程B释放了锁

 

notifyAll----从等待队列中取出所有线程

概念小结:

某个线程在运行synchronized方法时,其他所有线程都会停止运行(错)

停止运行的只是想要获取同一个实例的锁的线程。

wait方法的调用必须在synchronized方法中(错)

调用wait方法的语句可以写在synchronized方法中和代码块中,或者二者调用的其他方法中,只要执行方法的线程在执行时获取了对象实例的锁即可。

3. Single Threaded Execution

Gate 类:
public class Gate {
private int counter = 0;

private String name = "Nobody";

private String address = "Nowhere";

public  void pass(String name,String address){
this.counter++;
this.name = name;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.address = address;
check();
}
public  String toStr(){
return "No." + counter+":"+name+","+address;
}
public void check(){
if(name.charAt(0)!= address.charAt(0)){
System.out.println("Broken"+toStr());
}
}

}

UserThread类:

public class UserThread extends Thread{
private final Gate gate;

private final String myname;

private final String myaddress;


public UserThread2(Gate gate, String myname, String myaddress) {
this.gate = gate;
this.myname = myname;
this.myaddress = myaddress;
}

public void run(){
System.out.println(myname+"begin");
while(true){
gate.pass(myname, myaddress);
}
}


}

public static void main{

Gate gate = new Gate();

new UserThread(gate, "Alice", "Asian").start();

new UserThread(gate, "Bobby", "Brazil").start();

new UserThread(gate, "Chris", "Canada").start();

this.counter++;

this.name = name;

this.address = address;

check();

 }

解决方法:在pass()方法前加上synchronized

使用Single Threaded Execution模式的情况

1.多线程时

2.数据可被多个线程访问

3.状态可能改变

4.需要确保数据安全性

在使用Single Threaded Execution,会存在发生死锁的危险

1.存在多个SharedResource角色(参与者)

2.线程在持有着某个SharedResource角色的锁的同时,还想获取其他SharedResource角色的锁

3.获取SharedResource角色的锁的顺序并不固定

比喻两个意大利吃拉面的例子(两个人吃面只有一个勺子和叉子,但是勺子和叉子缺一不可,一个人拿着叉子,一个人拿着勺子):

1.存在多个SharedResource角色(参与者)相当于叉子和勺子

2.线程在持有着某个SharedResource角色的锁的同时,还想获取其他SharedResource角色的锁 相当于拿着叉子还想要勺子

3.获取SharedResource角色的锁的顺序并不固定 拿叉子和拿勺子的顺序并不一样

继承反复性:

对于多线程来说,继承会出现很多问题

.Single Threaded Execution 降低程序性能

1. 获取锁花费的时间

2. 线程冲突引起的等待

 

Semaphore的使用

semaphone.acquire()用于确认是否存在可用资源,当所有资源已被使用时,线程会阻塞在此方法中

semaphone.release()方法释放所用的资源

semaphone.avaliablePermits()表示当前正在使用的资源个数

猜你喜欢

转载自blog.csdn.net/qq_31350373/article/details/80273246