一、线程的常用方法

1、Thread(String name):初始化线程的名字
2、 setName(String name):设置线程的名字
3、 getName():返回线程的名字
4、 sleep(long millis):线程睡眠指定毫秒数.静态的方法.
5、 currentThread(): 返回当前线程对象
6、 getPriority():返回当前线程对象的优先级  默认优先级5
7、 setPriority(int newPriority):设置线程优先级   虽然设置了优先级,但是具体的实现取决于底层操作系统实现(最大优先级数是10,最小的是1,默认的是5)

8、其他几个方法,1.8、线程生命周期处 ..............

1.1、例1   Thread()、currentThread()

  1. package com.zn.thread;
  2.  
  3. /**
  4. * @author DSHORE / 2018-5-7
  5. *
  6. */
  7. public class Demo2 extends Thread {
  8.  
  9. public Demo2(String name) {
  10. super(name);
  11. }
  12. @Override
  13. public void run() {
  14. //Thread.currentThread():返回当前线程对象
  15. System.out.println("当前线程:"+Thread.currentThread());//运行结果:当前线程:Thread[二狗子线程,5,main];说明:当前线程是二狗子线程,优先级是5
  16. System.out.println("this:"+this);//运行结果:this:Thread[二狗子线程,5,main]
  17.  
  18. for(int i=;i<;i++){
  19. System.out.println(Thread.currentThread().getName()+i);
  20. }
  21. }
  22. public static void main(String[] args) {
  23. Demo2 d = new Demo2("二狗子线程");
  24. d.start();
  25.  
  26. System.out.println("当前线程:"+Thread.currentThread());//运行结果:当前线程:Thread[main,5,main] 说明:当前线程是主线程(main线程),优先级也是5
  27.  
  28. for(int j=;j<;j++){
  29. System.out.println("主线程:"+j);
  30. }
  31. }
  32. }

结果图

                   

1.2、例2    setName()、getName()

1、setName():设置线程的名字
    2、getName():获取线程的名字

  1. package com.zn.thread;
  2.  
  3. /**
  4. * @author DSHORE / 2018-5-7
  5. *
  6. */
  7. public class Demo2 extends Thread {
  8.  
  9. public Demo2(String name) {
  10. super(name);
  11. }
  12. @Override
  13. public void run() {//run()方法中的代码,都是自定义线程
  14. for(int i=;i<;i++){
  15. System.out.println(Thread.currentThread().getName()+i);//获取当前线程的名字
  16. }
  17. }
  18. public static void main(String[] args) {
  19. //创建一个线程对象
  20. Demo2 d = new Demo2("二狗子线程");
  21. d.setName("狗剩线程");//设置线程的名字
  22. d.start();
  23.  
  24. Thread.currentThread().setName("隔壁老王线程");
  25. for(int j=;j<;j++){
  26. System.out.println(Thread.currentThread().getName()+j);
  27. }
  28. }
  29. }

结果图      (狗剩线程 覆盖掉了 二狗子线程)

1.3、例3     sleep()

sleep():指定线程睡眠的时间(毫秒为单位)

  1. package com.zn.thread;
  2.  
  3. /**
  4. * @author DSHORE / 2018-5-7
  5. *
  6. */
  7. public class Demo2 extends Thread {
  8.  
  9. public Demo2(String name) {
  10. super(name);
  11. }
  12. @Override
  13. public void run() {
  14. for(int i=;i<;i++){
  15. System.out.println(Thread.currentThread().getName()+i);
  16. try {
  17. Thread.sleep();//休眠(暂停)100毫秒 1秒 = 1000毫秒
  18. } catch (InterruptedException e) {//Thread类的run方法没有抛出异常类型,所以子类不能抛出异常
  19. e.printStackTrace();//打印异常信息
  20. }
  21. }
  22. }
  23. public static void main(String[] args) {
  24. //创建一个线程对象
  25. Demo2 d = new Demo2("二狗子线程");
  26. d.start();
  27.  
  28. Thread.currentThread().setName("隔壁老王线程");
  29. for(int j=;j<;j++){
  30. System.out.println(Thread.currentThread().getName()+j);
  31. }
  32. }
  33. }

运行结果图  (其中一次的运行结果)

使用sleep()方法,睡了一下,几乎都被“隔壁老王全抢了线程”;二狗子线程在后面才执行

1.4、例4      getPriority()

getPriority():获取当前线程对象的优先级    默认优先级:5
setPriority():设置优先级数

  1. package com.zn.thread;
  2.  
  3. /**
  4. * @author DSHORE / 2018-5-7
  5. *
  6. */
  7.  
  8. public class Demo3 extends Thread {
  9. @Override
  10. public void run() {
  11. Thread t = new Thread();//先创建线程对象,再去获取优先级数或设置优先级数
  12. t.setPriority();//直接设置优先级
  13. for(int i=;i<;i++){
  14. System.out.println("当前线程:"+i+"\t"+t.getPriority());//getPriority():获取该线程对象的优先级数; 默认优先级是5
  15. }
  16. }
  17. public static void main(String[] args) {
  18. //创建一个线程对象
  19. Demo3 d = new Demo3();
  20. d.start();
  21.  
  22. Thread.currentThread().setName("隔壁老王线程");
  23. for(int j=;j<;j++){
  24. System.out.println(Thread.currentThread().getName()+j);
  25. }
  26. }
  27. }

结果图

                    

二、线程安全问题

2.1、java线程同步机制

方式一:同步代码块
         synchronized(锁对象){
               需要被同步的代码...
         }

方式二:同步函数

        修饰符 synchronized 返回值类型 函数名(参数类型  参数名){

}

  1. public synchronized void add(int a) { //即:在普通函数上面加个 synchronized
  2.  
  3. }

2.2、同步代码块要注意的问题

1.任意的一个对象都可以作为锁对象
    2.在同步代码块中调用了sleep并不是释放锁对象.
    3.只有真正存在线程安全问题是,才使用同步代码块,否则会降低效率
    4.多线程操作的锁对象必须是唯一共享的,否则就无效了

实例1 (出现线程安全问题)

  1. package com.zn.thread;
  2.  
  3. /**
  4. * @author DSHORE / 2018-5-8
  5. *
  6. * 模拟3个窗口同时在售20张票
  7. */
  8.  
  9. class Windows extends Thread{
  10. static int num=;//票数 问题1 //得使用static共享num给三个线程(w1、w2、w3)一起使用 注:这是第二张结果图的程序,第一张int num 前面是没有static的。
  11. public Windows(String name){
  12. super(name);
  13. }
  14. @Override
  15. public void run() {
  16. while(true){//问题2 此处应该加个同步锁
  17. if(num>){
  18. System.out.println(Thread.currentThread().getName()+"售出第"+num+"票");
  19. num--;
  20. }else{
  21.   System.out.println("票已售罄");
  22.   break;
  23. }
  24. }
  25. }
  26. }
  27. public class Demo3 {
  28. public static void main(String[] args) {
  29. //创建3个线程对象,模拟3个窗口
  30. Windows w1=new Windows("窗口1");
  31. Windows w2=new Windows("窗口2");
  32. Windows w3=new Windows("窗口3");
  33. //开启线程售票
  34. w1.start();
  35. w2.start();
  36. w3.start();
  37. }
  38. }

运行结果图

                                    

两张图都出现了“三个窗口都有售出同一张票的情况”;即:出现了线程安全问题,解决该问题看例2

问题1:为什么出现了:售出60张票?
    答:把num这个数据共享给三个线程对象使用,使用static
问题:出现线程安全问题
    线程安全问题的解决方案:sun提供了同步机制让我们解决这类问题

实例2 (完美实例)

  1. package com.zn.thread;
  2.  
  3. /**
  4. * @author DSHORE / 2018-5-8
  5. *
  6. * 模拟3个窗口同时在售20张票
  7. */
  8. //同步代码块 例子
  9. class Windows extends Thread{
  10. static int num = ;//票数
    //static Object o=new Object(); //多线程操作的锁对象必须是唯一共享
  11. public Windows(String name){
  12. super(name);
  13. }
  14. @Override
  15. public void run() {
  16. while(true){
  17. //同步代码块
  18. synchronized ("锁") { //synchronized (o){ } //任意的一个对象都可以作为锁对象
  19. if(num>){
  20. System.out.println(Thread.currentThread().getName()+"售出第"+num+"票");
  21. try {
  22. Thread.sleep();//睡眠100毫秒
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();//打印异常信息
  25. }
  26. num--;
  27. }else{
  28. System.out.println("票已售罄");
  29. break;
  30. }
  31. }
  32. }
  33. }
  34. }
  35. public class Demo3 {
  36. public static void main(String[] args) {
  37. //创建3个线程对象,模拟3个窗口
  38. Windows w1=new Windows("窗口1");
  39. Windows w2=new Windows("窗口2");
  40. Windows w3=new Windows("窗口3");
  41. //开启线程售票
  42. w1.start();
  43. w2.start();
  44. w3.start();
  45. }
  46. }

运行结果图

2.3、出现安全问题的根本原因

1.存在两个或者两个以上的线程对象,而且线程之间共享一个资源.
    2.有多个语句操作了共享资源

2.4、同步函数要注意的问题

1.如果是一个非静态的同步函数,锁对象是this对象(相当于全局变量)。如果是静态的同步函数的锁,对象是当前函数锁属的类的字节码文件(class对象)。
    2.同步函数锁对象是固定的,不能由你来指定

推荐使用同步代码块
    原因:
       1.同步代码块锁对象由我们随意指定,方便控制;同步函数锁对象是固定的,不能由我们指定
       2.同步代码块可以很方便的控制需要同步的范围,同步函数必须是整个函数的所有代码都被同步了.

  1. //需求:两人同时取钱(卡+本子)
  2.  
  3. //同步函数 例子
  4. class BankThread extends Thread{
  5. static int count=;
  6. public BankThread(String name) {
  7. super(name);
  8. }
  9. @Override
  10. public void run() {
  11. getMoney();
  12. }
      //同步函数
  13. public static synchronized void getMoney(){ //静态的函数---->函数所属的类的字节码文件对象 BanckThread.class唯一的
  14. while(true){
  15. if(count>){
  16. System.out.println(Thread.currentThread().getName()+"取走了10000,还剩"+(count-)+"元");
  17. count=count-;
  18. }else{
  19. System.out.println("取完了..滚蛋");
  20. break;
  21. }
  22. }
  23. }
  24. }
  25.  
  26. public class Demo1 {
  27. public static void main(String[] args) {
  28. BankThread b=new BankThread("狗蛋");
  29. BankThread b1=new BankThread("铁蛋");
  30. b.start();
  31. b1.start();
  32. }
  33. }
  34. //问题:结果只有一个人能取到钱,另一个人始终没办法取到钱。原因:同步函数把所有代码都锁住了;这里应该用同步代码块

三、死锁现象

java同步机制解决了线程安全问题,但是也同时引发了死锁现象

3.1、死锁现象出现的根本原因

1.存在两个或者两个以上的线程.
    2.存在两个或者两个以上共享资源.

3.2、死锁问题的解决方案

没有方案,只能尽量避免发生而已.

3.3、实例

  1. package com.zn.thread;
  2.  
  3. /**
  4. * @author DSHORE / 2018-5-11
  5. *
  6. * java同步机制解决了线程安全问题,但是也同时引发了了死锁现象
  7. *
  8. * 需求:两个人抢着去打开电视机,但遥控器和电池是分开的,只有一个人同时拿到遥控器和电池才能打开电视机
  9. */
  10. class DeadLock extends Thread{
  11. public DeadLock(String name) {
  12. super(name);
  13. }
  14. @Override
  15. public void run() {
  16. if("张三".equals(Thread.currentThread().getName())){
  17. synchronized ("电池") {
  18. System.out.println("张三拿到了电池,准备去拿遥控器");
  19. synchronized ("遥控器") {
  20. System.out.println("张三拿到了电池和遥控器,正在打开电视机 看电视");
  21. }
  22. }
  23. }else if("李四".equals(Thread.currentThread().getName())){
  24. synchronized ("遥控器") {
  25. System.out.println("李四拿到了遥控器,准备去拿电池");
  26. synchronized ("电池") {
  27. System.out.println("李四拿到了遥控器和电池,正在打开电视机中");
  28. }
  29. }
  30. }
  31. }
  32. }
  33. public class Demo4 {
  34. public static void main(String[] args) {
  35. //创建线程对象
  36. DeadLock d = new DeadLock("张三");
  37. DeadLock d1 = new DeadLock("李四");
  38. //开启线程
  39. d.start();
  40. d1.start();
  41. }
  42. }

运行结果图

    

原创作者:DSHORE

作者主页:http://www.cnblogs.com/dshore123/

原文出自:http://www.cnblogs.com/dshore123/p/9004156.html

欢迎转载,转载务必说明出处。(如果本文对您有帮助,可以点击一下右下角的 推荐,或评论,谢谢!

java基础25 线程的常用方法、线程安全问题、死锁现象的更多相关文章

  1. Java基础图解,JVM,线程,Spring,TCP,SpringMVC等开发体系图解

    Java基础图解,JVM,线程,Spring,TCP,SpringMVC等开发体系图解 1.Java虚拟机运行时数据区图 2. 堆的默认分配图 3.方法区结构图 4.对象的内存布局图 5.对象头的Ma ...

  2. Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

  3. JAVA基础知识之多线程——控制线程

    join线程 在某个线程中调用其他线程的join()方法,就会使当前线程进入阻塞状态,直到被join线程执行完为止.join方法类似于wait, 通常会在主线程中调用别的线程的join方法,这样可以保 ...

  4. java基础九[网络与线程](阅读Head First Java记录)

    网络socket连接 Java API的网络功能包(java.net)已经将底层的TCP连接等都封装好了,我们只需要通过Socket对象来建立客户端和服务器的连接,然后客户端能向服务器发送请求,并接收 ...

  5. JAVA基础知识系列---进程、线程安全

    1 相关概念 1.1 临界区 保证在某一时刻只有一个线程能访问数据的简便方法,在任意时刻只允许一个线程对资源进行访问.如果有多个线程试图同时访问临界区,那么在有一个线程进入后,其他所有试图访问临界区的 ...

  6. java基础回顾(五)线程详解以及synchronized关键字

    本文将从线程的使用方式.源码.synchronized关键字的使用方式和陷阱以及一些例子展开java线程和synchronized关键字的内容. 一.线程的概念 线程就是程序中单独顺序的流控制.线程本 ...

  7. Java基础知识(多线程和线程池)

    新建状态: 一个新产生的线程从新状态开始了它的生命周期.它保持这个状态直到程序 start 这个线程. 运行状态:当一个新状态的线程被 start 以后,线程就变成可运行状态,一个线程在此状态下被认为 ...

  8. Java基础教程——多线程:创建线程

    多线程 进程 每一个应用程序在运行时,都会产生至少一个进程(process). 进程是操作系统进行"资源分配和调度"的独立单位. Windows系统的"任务管理器&quo ...

  9. 毕向东JAVA基础25天教程目录

    视频目录:day01-01-基本常识day01-02-Java的跨平台性day01-03-Java环境搭建(安装)day01-04-Java环境搭建(环境变量配置)day01-05-Java环境搭建( ...

随机推荐

  1. 【spoj SUBLEX】 Lexicographical Substring Search

    http://www.spoj.com/problems/SUBLEX/ (题目链接) 题意 给出一个字符串,询问其中字典序第K小的子串. Solution 后缀自动机例题. 构出后缀自动机以后,对每 ...

  2. linux 第三周读书笔记-----第一二章 20135334赵阳林

    第一章 Linux内核简介 1.1 Unix的历史 由于Unix系统设计简洁并且在发布时提供源代码,所以许多其他组织和团体都对它进了进一步的开发. Unⅸ虽然已经使用了40年,但计算机科学家仍然认为它 ...

  3. WARNING: pgstat wait timeout

      在ELK的邮件报警中,发现了一个 WARNING: pgstat wait timeout 的报错信息,看字面意思是pgstat有关操作等待超时.   通过google查询,发现在pg的邮件列表中 ...

  4. mongodb 使用 robo3T 等工具添加用户之后还是 auth failed 的问题

    命令行输入 mongo use 对应的 db(需要授权的数据库),如 use admin 使用命令创建一个数据库,并赋予权限: db.createUser( { user: "xxx&quo ...

  5. struts的问题

    将SSH框架进行整合的时候,将三者的jar包加入到lib下面,然后测试struts,结果页面显示不出来报404错误,可是路径没有问题 找到罪魁祸首是:原因两个:(1)在未用到spring的时候,先不要 ...

  6. 读论文Machine Learning for Improved Diagnosis and Prognosis in Healthcare

    Deep Learning的基本思想 假设我们有一个系统S,它有n层(S1,…Sn),它的输入是I,输出是O,形象地表示为: I =>S1=>S2=>…..=>Sn => ...

  7. 实验一:使用ADO.NET方式读数据

    第一步:创建Asp.net应用程序 在VS中,点击文件->新建->项目,按如图方式选择并输入: 第二步:新建产品浏览网页窗体Listing.aspx: 在项目SportsStoreEx上点 ...

  8. 发送邮件 tp5.1 5.0都可以,实测有效

    https://www.cnblogs.com/zhensg123/p/8954175.html 博客文章少了个Expection.php 文件; common.php <?php // 应用公 ...

  9. Linux运维六:用户管理及用户权限设置

    Linux 系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统.用户的账号一方面可以帮助系统管理员对使用系统的用户进行 ...

  10. Docker简介与安装配置

    目录 Docker简介 什么是Docker 为啥要用容器 Docker Engine Docker架构说明 Docker安装 Docker版本介绍 Ubuntu安装docker-ce CentOS7安 ...