Java之线程,常用方法,线程同步,死锁

时间:2022-04-07 17:13:50

1, 线程的概念

进程与线程

进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)

线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)

切换而不是同步
一个程序中的方法有几条执行路径, 就有几个线程

Java中线程的生命周期

Java之线程,常用方法,线程同步,死锁

Java线程具有五中基本状态

新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就     绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

2, 线程的创建:

Thread类:

java.lang

Class Thread

  • All Implemented Interfaces:
    Runnable
    已知直接子类:
    ForkJoinWorkerThread

    线程是程序中执行的线程。 Java虚拟机允许应用程序同时执行多个执行线程。

    每个线程都有优先权。 具有较高优先级的线程优先于优先级较低的线程执行。 每个线程可能也可能不会被标记为守护程序。 当在某个线程中运行的代码创建一个新的Thread对象时,新线程的优先级最初设置为等于创建线程的优先级,并且当且仅当创建线程是守护进程时才是守护线程。

    创建一个新的执行线程有两种方法。 一个是将一个类声明为Thread的子类。 这个子类应该重写run类的方法Thread

    另一种方法来创建一个线程是声明实现类Runnable接口。 那个类然后实现了run方法。 然后可以分配类的实例,在创建Thread时作为参数传递,并启动。

两种方式:
1, 继承Thread类
class TestThread extends Thread {......}

 1 package com.hanqi.maya.test;
 2
 3 import javax.swing.plaf.FontUIResource;
 4 import javax.swing.text.StyledEditorKit.ForegroundAction;
 5
 6 public class Threadtest {
 7     public static void main(String[] args) {
 8         MyThread mt=new MyThread();
 9         mt.start();//开启线程
10         for(int i=0;i<50;i++){
11             System.out.println("main"+i);
12         }
13     }
14 }
15 class MyThread extends Thread{ //通过继承Thread类的方法来创建多线程
16
17     public void run(){
18         for(int i=0;i<50;i++){
19             System.out.println("MyThead"+i);
20         }
21     }
22
23 }

2, 实现Runnable接口, 然后作为参数传入到Thread类的构造方法中
class TestThread implements Runnable {......}

 1 package com.hanqi.maya.test;
 2
 3 import javax.swing.plaf.FontUIResource;
 4 import javax.swing.text.StyledEditorKit.ForegroundAction;
 5
 6 public class Threadtest {
 7     public static void main(String[] args) {
 8         MyThread mt=new MyThread();
 9
10         Thread t=new Thread(mt);
11         t.start();//自动去找t中实现的Runnable方法
12         for(int i=0;i<50;i++){
13             System.out.println("main"+i);
14         }
15 /*
16         mt.start();//开启线程
17         for(int i=0;i<50;i++){
18             System.out.println("main"+i);
19         }*/
20     }
21 }
22
23 class MyThread implements Runnable{ //通过继承Thread类的方法来创建多线程
24
25     public void run(){
26         for(int i=0;i<50;i++){
27             System.out.println("MyThead"+i);
28         }
29     }
30
31 }
32 /*class MyThread extends Thread{ //通过继承Thread类的方法来创建多线程
33
34     public void run(){
35         for(int i=0;i<50;i++){
36             System.out.println("MyThead"+i);
37         }
38     }
39
40 }*/

线程的启动:

调用线程类中的start()方法, 不能直接调用run()方法, 直接调用run()方法是方法调用, 不是启动线程

3, 线程常用方法

Java之线程,常用方法,线程同步,死锁

isAlive()
判断线程是否还活着, 调用start()之前和终止之后都是死的, 其他的都是活的

判断线程是否还在

 1 package com.hanqi.maya.test;
 2
 3 public class TestThread1 {
 4     public static void main(String[] args) {
 5         MyThread1 mt=new MyThread1();
 6
 7         Thread t=new Thread(mt);
 8
 9         System.out.println(t.isAlive());//判断线程是否还在,此处线程未开启
10         t.start();
11         System.out.println(t.isAlive());//判断线程是否还在,此处线程已经开启
12     }
13 }
14
15 class MyThread1 implements Runnable{ //通过继承Thread类的方法来创建多线程
16
17     public void run(){
18         for(int i=0;i<50;i++){
19             System.out.println("MyThead"+i);
20         }
21     }
22 }

优先级

getPriority()
setPriority()
设置优先级, 优先级的概念: 谁的优先级高, 谁执行的时间就多
Thread里面的默认优先级:
Thread.MIN_PRIORITY = 1
Thread.MAX_PRIORITY = 10
Thread.NORM_PRIORITY = 5

 1 package com.hanqi.maya.test;
 2
 3 public class TestPriority {
 4     public static void main(String[] args) {
 5         MyThread11 mt1 = new MyThread11("超人");
 6         MyThread2 mt2 = new MyThread2("蝙蝠侠");
 7         mt1.setPriority(Thread.NORM_PRIORITY + 5);//设置优先级
 8         mt1.start();
 9         mt2.start();
10         System.out.println("123");
11         try {
12             Thread.sleep(2000);
13         } catch (InterruptedException e) {
14             // TODO Auto-generated catch block
15             e.printStackTrace();
16         }
17         System.out.println(456);
18     }
19 }
20
21
22 class MyThread11 extends Thread {
23
24     public MyThread11(String name) {
25         super(name);//调用父类构造方法将name穿减去
26     }
27
28     public void run() {
29         for (int i = 0; i < 50; i++) {
30             System.out.println(this.getName() + ": " + i);
31         }
32     }
33 }
34
35 class MyThread2 extends Thread {
36
37     public MyThread2(String name) {
38         super(name);
39     }
40
41     public void run() {
42         for (int i = 0; i < 50; i++) {
43             System.out.println(this.getName() + ": " + i);
44         }
45     }
46 }

沉睡和终止

interrupt()
停止线程

这个方法要配合延迟使用,不要直接启动线程然后直接使用此方法

 1 package interupt;
 2
 3 import java.util.Date;
 4
 5 public class TestInterupt {
 6     public static void main(String[] args) {
 7         MyNewThread mnt = new MyNewThread();
 8         Thread t = new Thread(mnt);
 9         t.start();
10         try {
11             Thread.sleep(5000);
12         } catch (InterruptedException e) {
13             e.printStackTrace();
14         }
15         t.interrupt();
16         t.stop();
17 //         终止线程, 将run方法结束, 线程就结束了
18         MyNewThread.flag = false;
19     }
20 }
21
22 class MyNewThread implements Runnable {
23
24     static boolean flag = true;
25     @Override
26     public void run() {
27         while(flag) {
28             System.out.println(new Date());
29             try {
30                 Thread.sleep(1000);
31             } catch (Exception e) {
32                 System.out.println("线程终止 !");
33                 System.out.println(e.getMessage());
34                 return;
35             }
36         }
37     }
38
39 }

Thread.sleep(long millions)将程序暂停一会,暂停当前线程,如果没有线程也可以给普通程序暂停,需要抛出一个异常即可

 1 package com.hanqi.maya.test;
 2
 3 import java.util.Date;
 4
 5 public class TestInterupt {
 6     public static void main(String[] args) {
 7         MyNewThread mnt = new MyNewThread();
 8         Thread t = new Thread(mnt);
 9         t.start();
10         try {
11             Thread.sleep(5000);//先沉睡5s
12         } catch (InterruptedException e) {
13             e.printStackTrace();
14         }
15         /*t.interrupt();//调用会抛出异常
16         t.stop();//不建议使用,已经过时
17 *///         终止线程, 将run方法结束, 线程就结束了
18         MyNewThread.flag = false;//更改属性终止线程
19     }
20 }
21
22 class MyNewThread implements Runnable {
23
24     static boolean flag = true;
25     @Override
26     public void run() {
27         while(flag) {
28             System.out.println(new Date());
29             try {
30                 Thread.sleep(1000);//延迟一秒
31             } catch (Exception e) {
32                 System.out.println("线程终止 !");
33                 System.out.println(e.getMessage());
34                 return;
35             }
36         }
37     }
38
39 }

join()
合并线程

 1 package join;
 2
 3 public class TestJoin {
 4     public static void main(String[] args) {
 5         NewThread nt = new NewThread();
 6         nt.start();
 7         try {
 8             nt.join();//合并线程,继承自Thread,将这个线程加到当前线程,先执行这个线程
 9         } catch (InterruptedException e) {
10             e.printStackTrace();
11         }
12
13         for (int i = 0; i < 10; i++) {
14             System.out.println("我是main线程-----" + i);
15         }
16     }
17 }
18
19 class NewThread extends Thread {
20     public void run() {
21         for (int i = 0; i < 10; i++) {
22             System.out.println("我是NewThread线程=====" + i);
23         }
24     }
25 }

yield()---礼让
让出CPU执行其他线程

 1 package com.hanqi.maya.test;
 2
 3 public class TestPriority {
 4     public static void main(String[] args) {
 5         MyThread11 mt1 = new MyThread11("超人");
 6         MyThread2 mt2 = new MyThread2("蝙蝠侠");
 7         mt1.setPriority(Thread.NORM_PRIORITY + 5);//设置优先级
 8         mt1.start();
 9         mt2.start();
10         System.out.println("123");
11         try {
12             Thread.sleep(2000);
13         } catch (InterruptedException e) {
14             // TODO Auto-generated catch block
15             e.printStackTrace();
16         }
17         System.out.println(456);
18     }
19 }
20
21
22 class MyThread11 extends Thread {
23
24     public MyThread11(String name) {
25         super(name);//调用父类构造方法将name穿减去
26     }
27
28     public void run() {
29         for (int i = 0; i < 50; i++) {
30             System.out.println(this.getName() + ": " + i);
31         }
32     }
33 }
34
35 class MyThread2 extends Thread {
36
37     public MyThread2(String name) {
38         super(name);
39     }
40
41     public void run() {
42         for (int i = 0; i < 50; i++) {
43             System.out.println(this.getName() + ": " + i);
44         }
45     }
46 }

wait()

  • 导致当前线程等待,直到另一个线程调用此对象的notify()方法或notifyAll()方法,或指定的时间已过。

notify()

  • public final void notify()
    唤醒正在等待对象监视器的单个线程。 如果任何线程正在等待这个对象,其中一个被选择被唤醒。 选择是任意的,并且由实施的判断发生。 线程通过调用wait方法之一等待对象的监视器。

    唤醒的线程将无法继续,直到当前线程放弃此对象上的锁定为止。 唤醒的线程将以通常的方式与任何其他线程竞争,这些线程可能正在积极地竞争在该对象上进行同步; 例如,唤醒的线程在下一个锁定该对象的线程中没有可靠的权限或缺点。

notifyAll()---

  • public final void notifyAll()
    唤醒正在等待对象监视器的所有线程。 线程通过调用wait方法之一等待对象的监视器。

    唤醒的线程将无法继续,直到当前线程释放该对象上的锁。 唤醒的线程将以通常的方式与任何其他线程竞争,这些线程可能正在积极地竞争在该对象上进行同步; 例如,唤醒的线程在下一个锁定该对象的线程中不会有可靠的特权或缺点。

4, 线程同步
synchronized

线程的同步是保证多线程安全访问竞争资源的一种手段。

当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到的执行。

线程同步的真实意思和字面意思恰好相反。线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。

比如银行取钱:

银行卡余额3000,A从取款机取2000,B也想从支付宝这张卡转出2000,这时就要用到线程同步

线程同步,可以在方法声明中用 synchronized 关键字

也可以用 synchronized 关键字将代码块包起来实现

 1 package com.hanqi.util;
 2
 3 public class Bank {
 4     public int money=3000;
 5
 6     public /*synchronized*/ void getMoney(String name,int mon){
 7         synchronized(this){
 8             if(money>mon&&money>0){
 9                 try {
10                     Thread.sleep(1);
11                 } catch (InterruptedException e) {
12                     e.printStackTrace();
13                 }
14
15                 money-=mon;
16                 System.out.println("hi,"+name);
17                 System.out.println("取款"+mon);
18                 System.out.println("余额:"+money);
19
20             }else{
21                 System.out.println("hi,"+name);
22                 System.out.println("取款失败");
23                 System.out.println("余额:"+money);
24             }
25         }
26     }
27 }
 1 package com.hanqi.util;
 2
 3 public class Threadt1 {
 4
 5     public static void main(String[] args) {
 6         MyThread mt=new MyThread();
 7
 8         Thread t1=new Thread(mt);
 9         Thread t2=new Thread(mt);
10
11         t1.setName("Tom");
12         t2.setName("BomSa");
13
14         t1.start();
15         t2.start();
16     }
17 }
18 class MyThread implements Runnable{
19     public Bank bank=new Bank();
20     @Override
21     public void run() {
22         bank.getMoney(Thread.currentThread().getName(), 2000);
23     }
24 }

五、死锁概念

所谓死锁,是两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。

 1 package com.hanqi.util;
 2
 3 public class Deadlock implements Runnable {
 4
 5
 6     public static void main(String[] args) {
 7
 8         Deadlock d1 = new Deadlock();
 9         Deadlock d2 = new Deadlock();
10
11         d1.flag = 1;
12         d2.flag = 2;
13
14         Thread t1 = new Thread(d1);
15         Thread t2 = new Thread(d2);
16
17         t1.start();
18         t2.start();
19
20     }
21
22     public static Object obj1 = new Object();
23     public static Object obj2 = new Object();
24
25     public int flag;
26
27     @Override
28     public void run() {
29         if (flag == 1) {
30             System.out.println("这是第" + flag + "个线程");
31             synchronized (obj1) {
32                 try {
33                     Thread.sleep(500);
34                 } catch (InterruptedException e) {
35                     e.printStackTrace();
36                 }
37                 synchronized (obj2) {
38                     System.out.println("第" + flag + "个线程结束");
39                 }
40             }
41         }
42
43         if (flag == 2) {
44             System.out.println("这是第" + flag + "个线程");
45             synchronized (obj2) {
46                 try {
47                     Thread.sleep(500);
48                 } catch (InterruptedException e) {
49                     e.printStackTrace();
50                 }
51                 synchronized (obj1) {
52                     System.out.println("第" + flag + "个线程结束");
53                 }
54             }
55         }
56
57     }
58
59 }

Java之线程,常用方法,线程同步,死锁的更多相关文章

  1. Java线程和多线程(三)——线程安全和同步

    线程安全在Java中是一个很重要的课题.Java提供的多线程环境支持使用Java线程.我们都知道多线程共享一些对象实例的话,可能会在读取和更新共享数据的事后产生数据不一致问题. 线程安全 之所以会产生 ...

  2. Java基础学习笔记: 多线程,线程池,同步锁(Lock,synchronized )&lpar;Thread类&comma;ExecutorService ,Future类&rpar;(卖火车票案例)

    多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念.进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线 ...

  3. Java线程:线程的同步与锁

    一.同步问题提出 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据. public ...

  4. &lpar;转&rpar;Java线程:线程的同步与锁

      Java线程:线程的同步与锁       一.同步问题提出   线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 例如:两个线程ThreadA.ThreadB都操作同一个对象Fo ...

  5. Java学习笔记之——线程的生命周期、线程同步

    一. 线程的生命周期 新建(new Thrad):创建线程后,可以设置各个属性值,即启动前 设置 就绪(Runnable):已经启动,等待CPU调动 运行(Running):正在被CPU调度 阻塞(B ...

  6. 线程池,多线程,线程异步,同步和死锁,Lock接口

    线程池 线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源. 除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源.线程 ...

  7. Java并发编程,互斥同步和线程之间的协作

    互斥同步和线程之间的协作 互斥同步 Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是 JVM 实现的 synchronized,而另一个是 JDK 实现的 ReentrantLo ...

  8. Java多线程面试题:线程锁&plus;线程池&plus;线程同步等

    1.并发编程三要素? 1)原子性 原子性指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行. 2)可见性 可见性指多个线程操作一个共享变量时,其中一个线程对变量 ...

  9. Java多线程编程&lpar;4&rpar;--线程同步机制

    一.锁 1.锁的概念   线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题.锁 ...

  10. Java多线程并发02——线程的生命周期与常用方法,你都掌握了吗

    在上一章,为大家介绍了线程的一些基础知识,线程的创建与终止.本期将为各位带来线程的生命周期与常用方法.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程生命周期 一个线程不是被创建了 ...

随机推荐

  1. &lt&semi;十五&gt&semi;JDBC&lowbar;使用 DBUtils 进行更新、查询操作

    详解待续... DBUtilsTest.java import java.sql.Connection;import java.sql.Date;import java.sql.ResultSet;i ...

  2. Tomcat中JVM内存溢出及合理配置及maxThreads如何配置&lpar;转&rpar;

    来源:http://www.tot.name/html/20150530/20150530102930.htm Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚 ...

  3. Python3基础 sort&lpar;reverse&equals;True&rpar; 将一个列表降序排列

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  4. 【matlab】用matlab 保存带标记图像、图片的方法总结

    最近看了一些用matlab对图形图片进行保存的帖子和资源,关于图像保存的方法给大家分享一下这些方法是大家所使用方法的一个总结. 如今常用的方法有三种printf,imwrite,saveas下面分别介 ...

  5. Magicodes&period;WeiChat——媒体资源选择组件之media-choice(开源)

    media-choice为媒体资源选择组件,基于KnockoutJs.支持图片.语音.视频.图文的选择以及预览,支持默认选择类型,支持是否禁用选择类型的更改. 使用示例: <script id= ...

  6. 关于textjs的tree带复选框的树

    通过查阅一些资料和自己之前了解到的一些相关知识,有时项目中需要用到.话不多说,先看一下效果图: 我写的这人员选择的树,主要是改写了TreePanel,如下代码: ExtendTreePanel.js ...

  7. InnoDB还是MyISAM &lpar;摘录&rpar;

    两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用. 我作为使用MySQL的用户角度出发,Innodb和My ...

  8. OCP 11G 实验环境安装文档 &lpar; RedHat5&period;5 &plus; Oracle11g &rpar;

    RedHat5.5 linux下Oracle11g软件安装 一.配置虚拟机 为了创建和配置虚拟机,你需要添加硬件设备如磁盘和cpu,在你开始安装之前,创建一个windows目录作为存放虚拟机的目录 目 ...

  9. 【转】mysql数据库优化大全

    数据库优化 sql语句优化 索引优化 加缓存 读写分离 分区 分布式数据库(垂直切分) 水平切分 MyISAM和InnoDB的区别: 1. InnoDB支持事务,MyISAM不支持,对于InnoDB每 ...

  10. CentOS-7&period;2安装Ambari-2&period;6&period;1

    CentOS-7.2安装Ambari-2.6.1 一.Ambari 是什么? Ambari 跟 Hadoop 等开源软件一样,也是 Apache Software Foundation 中的一个项目, ...