一、线程安全问题:

    当我们使用多个线程操作统一方法内的局部变量的时候,每个局部变量在当前线程里都有自己的副本,这种情况是不会出现线程安全问题的。当我们两个线程同时操作全局变量的时候,有可能会引发线程安全的问题。
 
①.业务类

  1. package com.multiThread.bean;
  2. publicclassAservise{
  3. privateString name;
  4. publicvoid doBusiness(String name){
  5. this.name = name;
  6. System.out.println("大家好,我是"+this.name);
  7. }
  8. }
②.线程类
  1. package com.multiThread.thread;
  2. import com.multiThread.bean.Aservise;
  3. publicclassUnSafeThreadimplementsRunnable{
  4. privateAservise aServise;
  5. privateString name;
  6. publicUnSafeThread(Aservise aServise,String name){
  7. this.aServise = aServise;
  8. this.name = name;
  9. }
  10. @Override
  11. publicvoid run(){
  12. aServise.doBusiness(this.name);
  13. }
  14. }
③.测试类
  1. package com.multiThread.test.common;
  2. import com.multiThread.bean.Aservise;
  3. import com.multiThread.thread.UnSafeThread;
  4. publicclassUnSafeThreadTest{
  5. publicstaticvoid main(String[] args){
  6. Aservise aService =newAservise();
  7. UnSafeThread unSafeThreadZhang =newUnSafeThread(aService,"张三");
  8. UnSafeThread unSafeThreadLi =newUnSafeThread(aService,"李四");
  9. Thread zhang =newThread(unSafeThreadZhang);
  10. Thread li =newThread(unSafeThreadLi);
  11. zhang.start();
  12. li.start();
  13. }
  14. }
预期输出结果
  1. 大家好,我是张三
  2. 大家好,我是李四
多次运行实际输出结果
  1. 大家好,我是李四
  2. 大家好,我是李四
  3. 大家好,我是张三
  4. 大家好,我是李四
  5. 大家好,我是张三
  6. 大家好,我是张三
这个例子很好的解释了多个线程同时操作全局变量会存在线程安全的问题。
那么这种问题该如何解决呢?在这里我们只讨论服务器为单节点的情况,不考虑集群模式。
解决的方式是加锁,只要保证这两段程序不同时变更全局变量就OK。
 
 
将业务类的doBusiness方法更改为使用synchronized关键字修饰就可以:
1.在方法上声明,给当前对象加锁(非静态方法):
  1. publicsynchronizedvoid doBusiness(String name){
  2. this.name = name;
  3. System.out.println("大家好,我是"+this.name);
  4. }
 
2.synchronized不仅仅可以在方法上声明,也可以在方法内部声明(参数是Object类型的值,写成this代表给当前对象上锁)。这种情况叫做同步代码块:
  1. publicvoid doBusiness(String name){
  2. synchronized(this){
  3. this.name = name;
  4. System.out.println("大家好,我是"+this.name);
  5. }
  6. }
对象监视器:
    synchronize修饰方法或者synchronized(this),对象监视器监视当前类的对象。
    synchronize(其他对象),对象监视器给其他对象上锁。
需要注意的问题:
    一般不会使用字符串作为监视对象,因为字符串有个常量池的概念,在不同的地方操作可能锁的是同一个对象。
synchronize作用:
    1.给对象监视器监视的对象上锁
    2.保证同一时间只有一个对象可以获得此对象监视器上的锁。
 
注意:
    ①.synchronize关键字如果在非静态方法上声明或者在非静态代码块上声明synchronized(this),代表给当前对象上锁,当一个线程获得此锁的同时,其他线程调用synchronize修饰的方法、代码块均需等待。当此线程执行完毕或者主动释放锁时,根据cpu调度看哪个线程能获得此锁。
    ②.如果synchronize(其他对象),则代表给参数中的对象上锁,所有参数对象共用同一把锁,只有获得锁的线程可以执行此代码块。
    ③.如果是静态方法,则代表是给整个类上锁,那么整个类共用同一把锁,只有获得锁的线程可以执行同步方法、代码块。
 
使用jstack查看死锁:
    
    ①.cd到jdk/bin目录下,执行jps命令,得到正在运行的进程id,这块我笔记本上运行不出来。我也不知道哪个是进程id。
    ②.执行jstack - l 进程id
    ③.得到jstack后分析一下程序哪个地方设计有bug,修改程序。
 
二、Thread类相关API操作:
    
好了,现在我们已经对多线程和线程安全有了一定的认识。下面我们通过具体代码来了解一下java.lang.Thread类相关的API的常用操作。
 
currentThread():获取当前执行当前线程的线程对象
isAlive():当前线程是否存活(正在执行)
sleep():使当前线程睡眠一段时间,参数单位毫秒
getId():获取当前线程的唯一标识
yield():释放当前线程的控制权,将控制权交由CPU调度。
interrupt():停止线程执行(只调用这个方法无法中止线程的执行,需要配合interrupted()才能中断线程。线程在sleep的情况下中断会抛异常并且清除停止状态的值,使之变为false
interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能。
                        此方法多次调用会有问题。比如第一次中断线程,再次调用则会清除中断状态。
isInterrupted():测试线程是否已中断。
setPriority ():设置线程的优先级,优先级越高,优先执行的几率越大。取值范围是1~10
 
jdk中不推荐使用的过期的方法以及原因
stop():强制中断当前线程。 强制停止某个线程可能会造成某些清理操作无法完成。而且会将对象的锁给清除掉,有可能会造成数据不一致的问题。
suspend():暂停当前线程的执行,此操作并不会释放锁,有锁独占的问题。
                另外如果在System.out.println()中暂停了线程,同步锁并未释放。其他有System.out.println()的地方就无法执行。
                因为Sysem.out.println()本身底层的实现也是基于synchronized的。一个对象占着锁不放,这边就一直得不到执行。
System.out.println()的实现:
  1. publicvoid println(String x){
  2. synchronized(this){
  3. print(x);
  4. newLine();
  5. }
  6. }
resume():恢复当前线程的执行,此操作并不会释放锁,有锁独占的问题。
 
    

多线程(二)~Thread类相关的API介绍的更多相关文章

  1. (转)多线程——继承Thread 类和实现Runnable 接口的区别

    java中我们想要实现多线程常用的有两种方法,继承Thread 类和实现Runnable 接口,有经验的程序员都会选择实现Runnable接口 ,其主要原因有以下两点: 首先,java只能单继承,因此 ...

  2. 多线程:Thread类的Join()方法

    多线程:Thread类的Join()方法 http://blog.163.com/hc_ranxu/blog/static/3672318220095284513678/ 当我们在线程B中调用Thre ...

  3. 多线程学习笔记(四)---- Thread类的其他方法介绍

    一.wait和 sleep的区别 wait可以指定时间也可以不指定时间,而sleep必须指定时间: 在同步中时,对cpu的执行权和锁的处理不同: wait:释放执行权,释放锁:释放锁是为了别人noti ...

  4. Java多线程01(Thread类、线程创建、线程池)

    Java多线程(Thread类.线程创建.线程池) 第一章 多线程 1.1 多线程介绍 1.1.1 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于 ...

  5. 多线程之 Thread类

    一.多线程第一种方式的实现步骤(继承Thread类) 代码演示: 1.定义MyThread类,继承Thread类 2.重写了里面的run方法,在run方法中定义线程要执行的任务 public clas ...

  6. Java中实现多线程继承Thread类与实现Runnable接口的区别

    Java中线程的创建有两种方式: 1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2.  通过实现Runnable接口,实例化Thread类 在实际应用中, ...

  7. Java 多线程之 Thread 类 和 Runnable 接口初步使用

    目录 Thread 类 Thread之定义线程类 Thread之开启线程 Runnable 接口 Runnable 之定义线程类 Runnable 之开启线程 @ Thread 类 Thread 类是 ...

  8. 多线程——继承Thread类实现一个多线程

    继承Thread类实现一个多线程 Thread类部分源码: package java.lang; //该类实现了Runnable接口 public class Thread implements Ru ...

  9. Java 多线程 (Thread 类)

    1.多线程 2.卖票 1.多线程实现 两种方式可以实现多线程: 继承 Thread 类,重写 run 方法:定义对象,调用 start 方法 创建类实现 Runnable 接口,作为实参传递给 thr ...

随机推荐

  1. web前端基础

    超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为了提供一种发布和接 ...

  2. tornado 01 路由、输入与输出

    tornado 01 路由.输入与输出 一.安装tornado pyvip@Vip:~$ workon py3env #安装python3的虚拟环境 (py3env) pyvip@Vip:~$ pip ...

  3. HDU_1028 Ignatius and the Princess III 【母函数的应用之整数拆分】

    题目: "Well, it seems the first problem is too easy. I will let you know how foolish you are late ...

  4. PIE SDK微分锐化

    1.算法功能简介 微分锐化通过微分使图像的边缘或轮廓突出.清晰.导数算子具有突出灰度变化的作用,对图像运用导数算子,灰度变化较大的点处算得的值较高,因此我们将图像的导数算子运算值作为相应的边界强度,所 ...

  5. 《阿里如何实现秒级百万TPS?搜索离线大数据平台大数据平台架构解读》读后感

    在使用淘宝时发现搜索框很神奇,它可以将将我们想要的商品全部查询出来,但是我们并感觉不到数据库查询的过程,速度很快.通过阅读这篇文章让我知道了搜索框背后包含着很多技术,对我以后的学习可能很有借鉴. 平时 ...

  6. C语言两种方式实现矩阵的转置

    #include"stdio.h" typedef struct{ int i,j; int v; }Triple; typedef struct{ Triple date[]; ...

  7. oracle 笔记---(四)__数据字典

    数据字典 user_*  该视图存储了关于当前用户所拥有的对象的信息.(即所有在该用户模式下的对象) all_* 该试图存储了当前用户能够访问的对象的信息.(与user_*相比,all_* 并不需要拥 ...

  8. rancher 2.X 搭建小型web集群+mysql主从复制

    一,环境配置    rancher 2.1.6 二,配置harbor私有仓库 见上文 三,配置私有镜像 01,总文件 dockerfile 为主配置文件,html 为站点文件wordpress.,官网 ...

  9. Ubuntu 12.04 搭建 SAMBA-SWAT(Samba Web 管理工具)

    参考了:http://linux.chinaunix.net/techdoc/net/2007/03/14/952274.shtml,对其进行了部分修改完善. 依次执行 1.sudo apt-get ...

  10. (转)通过shell脚本实现批量添加用户和设置随机密码以及生产环境如何批量添加

    通过shell脚本实现批量添加用户和设置随机密码以及生产环境如何批量添加 原文:http://www.21yunwei.com/archives/4773 有一个朋友问我如何批量创建用户和设置密码 , ...