当前位置: 移动技术网 > IT编程>开发语言>Java > Java多线程记录(包含案例)

Java多线程记录(包含案例)

2020年05月02日  | 移动技术网IT编程  | 我要评论

线程是程序的执行单元,执行路径。是程序使用cpu的最基本单位

多线程 -- 程序有多条执行路径,提高应用进程的使用率

进程中线程越多,抢到cpu执行权概率越高。线程的执行有随机性

 

java程序的运行原理:

由java命令启动jvm,jvm启动就相当于启动了一个进程,接着由该程序创建了一个主线程去调用main方法

jvm的启动是多线程的,因为垃圾回收线程也要启动,否则容易出现内存溢出。(gc线程和主线程)

 

java多线程程序:

方法1:继承thread类,并重写run()方法,创建对象,执行对象。

  run()方法: thread类中的run()用来包含那些被线程执行的代码(封装被线程执行的代码)(不单独调用run方法(直接调用是普通方法),调用start())

  start()方法:首先启动了线程,然后再由jvm去调用该线程的run()方法

方法2:实现runnable接口

  a:自定义类实现runnable

  b:重写run()方法

  c:创建myrunnable类的对象 

  d:创建thread类的对象,把c步骤的对象作为构造参数传递

解决了java单继承的局限性,适合多个相同程序代码去处理同一个资源的情况,把线程相同的代码,数据有效分离

 

一些内建方法:

public final string getname()   //获取线程名称
public final string setname():    //设置线程名称
public static thread currentthread():    //返回当前正在执行的线程对象

 

抢占式调度模型(java):优先让优先级高的线程使用cpu

public final int getpriority():   //返回线程对象的优先级
public final void setpriority(): //设置线程优先级

优先级范围1-10,默认为5,最低为1,最高为5

 

线程控制:

public static void sleep(long millis)    //线程休眠
public final void join():   //线程加入   (等待线程终止)
public static void yield():  //线程礼让 暂停当前正在执行的线程对象,并执行其他线程
//让多个线程的执行更加和谐,但不能保证
public final void setdaemon(boolean on): //设置守护线程
//当正在运行的线程都是守护线程时,jvm退出,该方法必须在启动线程前调用
public void interrupt(): //中断线程,把线程的状态终止,并抛出一个interruptexception

 

线程的生命周期:(图解)

 

线程同步:synchronized关键字 

将多条语句操作的共享数据代码包成一个整体,让某个线程在执行的时候别人不执行

前提:多个线程;  注意:多个线程使用同一个锁对象

优点:解决了多线程的安全问题

缺点:当线程相当时,因为每个线程都会去判断同步上的锁,很耗费资源,无形中降低了程序的运行效率,容易产生死锁

使用同步代码块或者同步方法

 

死锁:

死锁代码举例:

1 public class mylock {
2     // 创建两把锁对象
3     public static final object obja = new object();
4     public static final object objb = new object();
5 }
 1 public class deadlock extends thread {
 2 
 3     private boolean flag;
 4 
 5     public deadlock(boolean flag) {
 6         this.flag = flag;
 7     }
 8 
 9     @override
10     public void run() {
11         if (flag) {
12             synchronized (mylock.obja) {
13                 system.out.println("if obja");
14                 synchronized (mylock.objb) {
15                     system.out.println("if objb");
16                 }
17             }
18         } else {
19             synchronized (mylock.objb) {
20                 system.out.println("else objb");
21                 synchronized (mylock.obja) {
22                     system.out.println("else obja");
23                 }
24             }
25         }
26     }
27 }
1 public class dielockdemo {
2     public static void main(string[] args) {
3         deadlock dl1 = new deadlock(true);
4         deadlock dl2 = new deadlock(false);
5 
6         dl1.start();
7         dl2.start();
8     }
9 }

 

等待唤醒机制:

object类提供三个方法:

wait() :等待

notify():唤醒单个线程

notifyall():唤醒所有线程

为什么不在thread类中: 因为这些方法必须通过锁对象调用,而锁对象可以是任意锁对象,所以定义在object类中

 

semaphore信号量:

信号量(semaphore),又被称为信号灯,在多线程环境下用于协调各个线程, 以保证它们能够正确、合理的使用公共资源。信号量维护了一个许可集,我们在初始化semaphore时需要为这个许可集传入一个数量值,该数量值代表同一时间能访问共享资源的线程数量。

线程可以通过acquire()方法获取到一个许可,然后对共享资源进行操作,注意如果许可集已分配完了,那么线程将进入等待状态,直到其他线程释放许可才有机会再获取许可,线程释放一个许可通过release()方法完成,"许可"将被归还给semaphore。

 

多线程案例:

电影院卖票:电影院一共有100张票,有三个窗口卖票,模拟电影院售票:

使用同步代码块:

public class sellticket implements runnable {
    // 定义100张票
    private int tickets = 100;
    //创建锁对象
    private object obj = new object();
    
    @override
    public void run() {
        while (true) {
            synchronized (obj) {
                if (tickets > 0) {
                    try {
                        thread.sleep(100);
                    } catch (interruptedexception e) {
                        e.printstacktrace();
                    }
                    system.out.println(thread.currentthread().getname()
                            + "正在出售第" + (tickets--) + "张票");
                }
            }
        }
    }
}
public class sellticketdemo {
    public static void main(string[] args) {
        // 创建资源对象
        sellticket st = new sellticket();

        // 创建三个线程对象
        thread t1 = new thread(st, "窗口1");
        thread t2 = new thread(st, "窗口2");
        thread t3 = new thread(st, "窗口3");

        // 启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

使用同步方法:

 1 package lab2;
 2 
 3 public class sellticket implements runnable {
 4 
 5     // 定义100张票
 6     private static int tickets = 100;
 7 
 8     @override
 9     public void run() {
10         while (true) {
11             sellticket();
12         }
13     }
14     
15      private synchronized void sellticket() {
16             if (tickets > 0) {
17             try {
18                     thread.sleep(100);
19             } catch (interruptedexception e) {
20                     e.printstacktrace();
21             }
22             system.out.println(thread.currentthread().getname()
23                         + "正在出售第" + (tickets--) + "张票 ");
24             }
25     }
26 }

使用锁方法:

 1 import java.util.concurrent.locks.lock;
 2 import java.util.concurrent.locks.reentrantlock;
 3 
 4 public class sellticket implements runnable {
 5 
 6     // 定义票
 7     private int tickets = 100;
 8 
 9     // 定义锁对象
10     private lock lock = new reentrantlock();
11 
12     @override
13     public void run() {
14         while (true) {
15             try {
16                 // 加锁
17                 lock.lock();
18                 if (tickets > 0) {
19                     try {
20                         thread.sleep(100);
21                     } catch (interruptedexception e) {
22                         e.printstacktrace();
23                     }
24                     system.out.println(thread.currentthread().getname()
25                             + "正在出售第" + (tickets--) + "张票");
26                 }
27             } finally {
28                 // 释放锁
29                 lock.unlock();
30             }
31         }
32     }
33 
34 }

 

ornamental garden problem:(使用bakery class) 花园有两个旋转门,可进可出,监控花园内的人数

volatile关键字: specifying a variable as volatile instructs the compiler to load and store the value of the variable at each use.   另外更多说明可以参考:https://www.cnblogs.com/daxin/p/3364014.html

bakery algorithm面包店算法

bakery.java

 1 package lab2;
 2 
 3 public class bakery {
 4     public int nthreads;
 5     
 6     private volatile int[] ticket;
 7     private volatile boolean[] choosing;
 8     
 9     bakery(int nth) {
10         nthreads = nth;
11         ticket = new int[nthreads];
12         choosing = new boolean[nthreads];
13         
14         for (int i = 0; i < nthreads; i++) {
15             system.out.println(i + ticket[1]);
16             ticket[i] = 0;
17             choosing[i] = false;
18         }
19     }
20     
21     private int getnextnumber() {
22         int largest = 0;
23         for (int i = 0; i < nthreads; i++) {
24             if (ticket[i] > largest)
25                 largest = ticket[i];
26         }
27         return largest + 1;
28     }
29     
30     private boolean isfavouredthread(int i, int j) {
31         if ((ticket[i] == 0) || (ticket[i] > ticket[j]))
32             return false;
33         else {
34             if (ticket[i] < ticket[j])
35                 return true;
36             else
37                 return (i < j);
38         }
39     }
40 
41     void wanttoentercs(int threadid) {
42         choosing[threadid] = true;
43         ticket[threadid] = getnextnumber();
44         choosing[threadid] = false;
45         
46         for (int otherthread = 0; otherthread < nthreads; otherthread++) {
47             while(choosing[otherthread]) {
48                 // busy-wait
49             }
50             // break any ties between threads
51             while (isfavouredthread(otherthread,threadid)) {
52                 // busy-wait
53             }
54         }
55     }
56 
57     void exitcs(int threadid) {
58         // leave critical section
59         ticket[threadid] = 0;
60     }
61 }

couter.java

 1 package lab2;
 2 
 3 public class counter {
 4     volatile int value = 0;
 5 
 6     counter() {
 7         system.out.println("total: " + value);
 8     }
 9 
10     boolean increment() {
11         int temp = value;   //read[v]
12         simulate.hwinterrupt();
13         value = temp + 1;       //write[v+1]
14         system.out.println("total: " + value);
15             return true;
16     }
17 
18     boolean decrement() {
19         int temp = value;   //read[v]
20         simulate.hwinterrupt();
21             if (temp == 0) return false;
22         simulate.hwinterrupt();
23         value = temp - 1;       //write[v+1]
24         system.out.println("total: " + value);
25             return true;
26     }
27 }
28 
29 class simulate {
30     public static void hwinterrupt() {
31         if (math.random() < 0.5)
32            try{
33                thread.sleep(200);
34            } catch(interruptedexception ie) {};
35     }
36 }

turnstile.java

 1 package lab2;
 2 
 3 /* notes:
 4  * no modifications need be made to the bakery class.  instead, the turnstile
 5  * class and counter classes are adjusted to allow for "exit" turnstiles as well
 6  * as entrance turnstiles.  this solution incorporates a system to prevent the
 7  * number of people in the gardens from being negative, so the sleep call in
 8  * this class can be commented out.  study the code in the counter and turnstile
 9  * classes to see how how this works.
10  * */
11 
12 public class gardens {
13      static turnstile west;
14      static turnstile east;
15      static turnstile westexit;
16      static turnstile eastexit;
17      static counter people;
18      static bakery bakery;
19      
20     public static void main(string[] args) {
21         people = new counter();
22         bakery = new bakery(4);
23          
24          west = new turnstile(0, true, people, bakery);
25          east = new turnstile(1, true, people, bakery);
26 
27          westexit = new turnstile(2, false, people, bakery);
28          eastexit = new turnstile(3, false, people, bakery);
29          
30          west.start();
31          east.start();
32 
33         /* 
34         try {
35             thread.sleep(5000);
36         } catch (interruptedexception e) {
37         }
38         */
39 
40         westexit.start();
41         eastexit.start();
42     }
43 }

garden.java

 1 package lab2;
 2 
 3 public class gardens {
 4      static turnstile west;
 5      static turnstile east;
 6      static turnstile westexit;
 7      static turnstile eastexit;
 8      static counter people;
 9      static bakery bakery;
10      
11     public static void main(string[] args) {
12         people = new counter();
13         bakery = new bakery(4);
14          
15          west = new turnstile(0, true, people, bakery);
16          east = new turnstile(1, true, people, bakery);
17 
18          westexit = new turnstile(2, false, people, bakery);
19          eastexit = new turnstile(3, false, people, bakery);
20          
21          west.start();
22          east.start();
23 
24         /* 
25         try {
26             thread.sleep(5000);
27         } catch (interruptedexception e) {
28         }
29         */
30 
31         westexit.start();
32         eastexit.start();
33     }
34 }

 

生产者消费者,操作列表:

buffer.java

 1 import java.util.linkedlist;
 2 import java.util.nosuchelementexception;
 3 
 4 class buffer {
 5     linkedlist<integer> queue = new linkedlist<integer>();
 6     
 7     public synchronized void write(int i) {
 8         queue.add(i);
 9     }
10 
11     public synchronized int read() {
12         try {
13             return queue.removefirst();
14         } catch(nosuchelementexception e) {
15             // the buffer is empty!?
16             return -1;
17         }
18     }
19 }

producer.java

 1 class producer implements runnable {
 2     buffer buffer;
 3 
 4     public producer(buffer b) {
 5         buffer = b;
 6     }
 7 
 8     public void run() {
 9         for(int i = 0; i < 20; i++) {
10             buffer.write(i);
11             system.out.println("thread " + thread.currentthread().getid() +
12                 " writes " + i);
13         }
14     }
15 }

consumer.java

 1 class consumer implements runnable {
 2     buffer buffer;
 3 
 4     public consumer(buffer b) {
 5         buffer = b;
 6     }
 7 
 8     public void run() {
 9         for(int i = 0; i < 10; i++) {
10             try {
11                 thread.sleep(10);
12             } catch (interruptedexception e) {
13             }
14             int x = buffer.read();
15             system.err.println("thread " + thread.currentthread().getid() +
16                 " reads " + x);
17         }
18     }
19 }

infbuffer.java

 1 public class infbuffer {
 2     public static void main(string args[]) {
 3         buffer b = new buffer();
 4         consumer c1 = new consumer(b);
 5         consumer c2 = new consumer(b);
 6         producer p = new producer(b);
 7         (new thread(c1)).start();
 8         (new thread(c2)).start();
 9         (new thread(p)).start();
10     }
11 }

 

生产者消费者,修改学生姓名和年龄并获取:(只能一打一大片,无法实现生产者生产后等待消费者消费后再产生)

1 public class student {
2     string name;
3     int age;
4 }
 1 public class setthread implements runnable {
 2 
 3     private student s;
 4     private int x = 0;
 5 
 6     public setthread(student s) {
 7         this.s = s;
 8     }
 9 
10     @override
11     public void run() {
12         while (true) {
13             synchronized (s) {
14                 if (x % 2 == 0) {
15                     s.name = "student1";
16                     s.age = 27;
17                 } else {
18                     s.name = "student2"; 
19                     s.age = 30;
20                 }
21                 x++;
22             }
23         }
24     }
25 }
 1 public class getthread implements runnable {
 2     private student s;
 3 
 4     public getthread(student s) {
 5         this.s = s;
 6     }
 7 
 8     @override
 9     public void run() {
10         while (true) {
11             synchronized (s) {
12                 system.out.println(s.name + "---" + s.age);
13             }
14         }
15     }
16 }
 1 public class studentdemo {
 2     public static void main(string[] args) {
 3         //创建资源
 4         student s = new student();
 5         
 6         //设置和获取的类
 7         setthread st = new setthread(s);
 8         getthread gt = new getthread(s);
 9 
10         //线程类
11         thread t1 = new thread(st);
12         thread t2 = new thread(gt);
13 
14         //启动线程
15         t1.start();
16         t2.start();
17     }
18 }

 

生产者消费者,修改学生姓名和年龄并获取:(使用等待唤醒机制改进)

1 public class student {
2     string name;
3     int age;
4     boolean flag;  //添加一个标记,默认为false,表示生产者是否生成值
5 }
 1 public class setthread implements runnable {
 2 
 3     private student s;
 4     private int x = 0;
 5 
 6     public setthread(student s) {
 7         this.s = s;
 8     }
 9 
10     @override
11     public void run() {
12         while (true) {
13             synchronized (s) {
14                 //判断有没有
15                 if(s.flag) {
16                     try {
17                         s.wait();
18                     } catch (interruptedexception e) {
19                         e.printstacktrace();
20                     }
21                 } 
22                 
23                 if (x % 2 == 0) {
24                     s.name = "student1";
25                     s.age = 27;
26                 } else {
27                     s.name = "student2"; 
28                     s.age = 30;
29                 }
30                 x++;
31                 
32                 //修改标记
33                 s.flag = true;
34                 //唤醒线程
35                 s.notify();
36             }
37         }
38     }
49 }
 1 public class getthread implements runnable {
 2     private student s;
 3 
 4     public getthread(student s) {
 5         this.s = s;
 6     }
 7 
 8     @override
 9     public void run() {
10         while (true) {
11             synchronized (s) {
12                 if (!s.flag) {
13                     try {
14                         s.wait();
15                     } catch (interruptedexception e) {
16                         e.printstacktrace();
17                     }
18                 }
19                 system.out.println(s.name + "---" + s.age);
20                 
21                 //修改标记
22                 s.flag = false;
23                 //唤醒线程
24                 s.notify();
25                 
26             }
27         }
28     }
29 }
public class studentdemo {    //同上
    public static void main(string[] args) {
        //创建资源
        student s = new student();
        
        //设置和获取的类
        setthread st = new setthread(s);
        getthread gt = new getthread(s);

        //线程类
        thread t1 = new thread(st);
        thread t2 = new thread(gt);

        //启动线程
        t1.start();
        t2.start();
    }
}

 

厕所排队(使用信号量)

 1 import java.util.random;
 2 import java.util.concurrent.semaphore;
 3 
 4 class wc extends thread {
 5     private string name;
 6     private semaphore wc;
 7     
 8     public wc(string name, semaphore wc) {
 9         this.name = name;
10         this.wc = wc;
11     }
12     
13     @override
14     public void run() {
15         int availablepermit = wc.availablepermits();
16         if (availablepermit > 0) {
17             system.out.println(name+",好开心啊,我终于有坑了");
18         }else {
19             system.out.println(name+"怎么没有坑了。。。");
20         }
21         
22         try {
23             wc.acquire();
24             system.out.println(name+",好开心啊,我终于抢到了!");
25             thread.sleep(new random().nextint(1000));
26             system.out.println(name+",好爽啊,终于上完了!");
27             wc.release();
28         } catch (interruptedexception e) {
29 
30         }
31     }
32 }
33 
34 public class demo {
35     public static void main(string[] args) {
36         semaphore semaphore = new semaphore(3);
37         
38         for (int i = 0; i < 10; i++) {
39             wc wc = new wc("第"+i+"个人", semaphore);
40             wc.start();
41         }
42     }
43 }

 

the sleeping barber (生产者消费者,信号量)

 1 import java.util.concurrent.semaphore;
 2 
 3 public class barber implements runnable{
 4 
 5     semaphore customerwaiting, seats, barbersleeping;
 6     
 7     barber(semaphore customerwaiting, semaphore seats, semaphore barbersleeping) {
 8         this.customerwaiting = customerwaiting;
 9         this.seats = seats;
10         this.barbersleeping = barbersleeping;
11     }
12     
13     public void run() {
14         
15         while (true){
16             
17             // get a customer, sleep otherwise
18             try {
19                 customerwaiting.acquire();
20             } catch (interruptedexception e) {}
21 
22             // cut the hair of the customer    
23             system.out.println("cutting hair");
24             barbersleeping.release();            
25             
26         }
27     }
28 }
 1 import java.util.concurrent.semaphore;
 2 
 3 public class customer implements runnable{
 4 
 5     semaphore customerwaiting, seats, barbersleeping;
 6 
 7     boolean cut = false;
 8     customer(semaphore customerwaiting, semaphore seats, semaphore barbersleeping) {
 9         this.customerwaiting = customerwaiting;
10         this.seats = seats;
11         this.barbersleeping = barbersleeping;
12 
13     }
14     
15     public void run() {
16         while (!cut) {
17             
18             // a random delay
19             // don't want all the threads trying at once!
20             try {
21                 thread.sleep((long)(math.random()*100));
22             } catch (interruptedexception e1) {}
23             
24             // try to get a seat in the waiting room
25             try {
26                 seats.acquire();
27             } catch (interruptedexception e) {}
28             system.out.println(seats.availablepermits());
29 
30                 system.out.println(thread.currentthread().getname()+" is sitting down");
31                 // try and wake barber
32                 customerwaiting.release();
33 
34                 
35                 // get hair cut
36                 try {
37                     barbersleeping.acquire();
38                 } catch (interruptedexception e) {}
39                 cut = true;
40                 seats.release();
41             
42         }
43         system.out.println(thread.currentthread().getname()+" has had hair cut");        
44     }
45 }
 1 import java.util.concurrent.semaphore;
 2 
 3 public class runner {
 4 
 5     public static void main(string[] args) {
 6         
 7         semaphore barbersleeping = new semaphore(1);
 8         semaphore customerwaiting = new semaphore(1);
 9         try {
10             customerwaiting.acquire();
11             barbersleeping.acquire();
12         } catch (interruptedexception e) {
13         }
14         
15         semaphore seats = new semaphore(3);
16         
17         barber bar = new barber(customerwaiting,seats,barbersleeping);
18         thread bthread = new thread(bar);
19         bthread.start();
20         
21         int ncust = 30;
22         customer customers[] = new customer[ncust];
23         thread cthread[] = new thread[ncust];
24         
25         for (int i=0;i<ncust;i++) {
26              customers[i] = new customer(customerwaiting,seats,barbersleeping);
27              cthread[i] = new thread(customers[i]);
28              cthread[i].start();
29         }
30     }
31 }

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网