java多线程(一)---Single Threaded Execution

单线程程序:处理流程始终一条线的程序。例如:无论是调用方法,还是执行for循环,if条件分支语句。甚至更复杂的处理,都不会对这条长线产生影响。在单线程程序中,“在某一时间点执行的处理”只有一个。“正在执行程序的主体”称为线程。

多线程程序:由多个线程组成的程序。例如:GUI应用程序,耗时的I/O处理,多个客户端。

并行:用于表示多个操作“同时处理”。

并发:用于表示“将一个操作分割成多个部分并且允许无序处理”。

启动线程的方法:(1)利用Thread类的子类的实例启动线程;eg:public class PrintThread extends Thread(2)利用Runnable接口的实现类的实例启动线程;eg:public class PrintThread implements Runnable

线程的互斥:synchronized,声明方法前加上关键字synchronized。加上可以确保该方法只能同时由一个线程执行。

临界区:只允许单个线程执行的程序范围。

 何时使用synchronized:(1)多线程时 (2)多个线程访问时 (3)状态有可能发生改变时(4)需要确保安全性时

死锁:两个线程分别持有着锁,并且相互等待对方释放锁的现象。

死锁发生的条件:(1)存在多个SharedSource角色 (2)线程在持有某个SharedResource角色的锁的同时,还想获取其他SharedResource角色的锁(3)获取SharedResource角色的锁的顺序并不固定(SharedResource角色是对称的)PS:只要破坏其中一个条件就可以防止死锁发生。

线程冲突:当线程A执行临界区内的处理时,其他想要进入临界区的线程会阻塞。

线程要执行synchronized的实例方法,必须获取this的锁,而能够获取一个实例的锁的线程线程只有 一个。

原子操作:不可分割的操作。例如:执行synchronized方法的操作。

java基本类型(int和char)和对象引用类型的赋值和引用操作也是原子的。但是long和double类型的操作不是原子。long和double在线程间共享时,需要将其放入synchronized中操作,或者声明为volatile。

死锁问题:例如两人同吃一盘食物,要用刀和叉,只有同时拥有刀和叉才能吃饭,预防出现一人拿刀一人拿叉的情况出现,可以设置两人拿工具的顺序,都为刀-叉或都为叉-刀,或者只有同时拥有两个工具才能吃饭。设置顺序的代码如下:

 1 public class PrintThread extends Thread{
 2     private String name;
 3     private final Tool lefthand;
 4     private final Tool righthand;
 5     public PrintThread(String name,Tool lefthand,Tool righthand) {
 6         this.name=name;
 7         this.lefthand=lefthand;
 8         this.righthand=righthand;
 9     }
10     public void run() {
11         while(true) {
12             eat();
13         }
14     }
15     public void eat() {
16         synchronized(lefthand) {
17             System.out.println(name+" takes up "+lefthand+"(left).");
18             synchronized(righthand) {
19                 System.out.println(name+" takes up "+righthand+"(left).");
20                 System.out.println(name+" is eating. ");
21                 System.out.println(name+" puts down "+lefthand+"(left).");
22                 System.out.println(name+" puts down "+righthand+"(left).");
23             }
24         }
25     }
26     public static class Tool{
27         private final String name;
28         public Tool(String name) {
29             this.name=name;
30         }
31         public String toString() {
32             return "["+name+"]";
33         }
34     }
35     
36 //public class Main() {
37     public static void main(String[] args) {
38         Tool spoon=new Tool("spoon");
39         Tool fork=new Tool("fork");
40         new PrintThread("Alice",spoon,fork).start();
41         new PrintThread("borry",spoon,fork).start();
42     }
43 }

 声明为final的类,无法创建子类。

延长临界区可以提高检查出错误的可能性,用sleep可以早点发现错误。

private字段只有在该类内部才可以访问;protected字段可以被该类的子类和同一个包内的类访问;public字段则可以被任何类访问。

猜你喜欢

转载自www.cnblogs.com/gtz-gdufs/p/12271582.html
今日推荐