主要内容

1.理解线程的并发性

2.线程的同步

3.线程的常用方法

  上一章中由于线程的并发性导致了多线程的执行总是会出现一些问题。。线程的并发性是程序员不可控制

的,也是不可避免的,线程的并发性往往会导致问题的出现。。那么我们为什么要控制线程的并发性呢?

如说:一个公子管理负责人正在修改雇员的工资表,而一些雇员正在领取工资,如果允许这样做必然会造成

混乱,因此,工资管理负责人正在修改工资表的时候,不允许任何的雇员领取工资,也就是说雇员们必须执行

等待状态。。

public class tickets {
public static void main(String[] args) {
sel s=new sel();
Thread t1=new Thread(s);
Thread t2=new Thread(s);
Thread t3=new Thread(s);
t1.start();
t2.start();
t3.start();
} }
class sel implements Runnable
{
private int num=100;
public void run()
{
while(true)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(num>0)
{
System.out.println(Thread.currentThread().getName()+"正在出售第"+num+"张票"+num--);
}else
{
break;
}
}
}
}

依然是卖票问题,上述的线程由于线程的并发性而导致了卖票窗口出现了问题。。

为了解决这一问题,我们引入线程的同步。。

2.线程的同步

 何为同步:我的理解就是:上述有三个线程,当t1线程启动的时候调用run()方法,那么同步函数也就起了作用,当t1执行run()

方法时,CPU分配给t1线程一把钥匙(并且只有一把),拿到这个钥匙之后开启synchronized函数的锁,然后进去执行里面的方法,

同时拿着钥匙,然后把门锁上,其他线程想访问这个函数的时候CPU没有钥匙,钥匙被线程t1拿进去了,所以其他的线程只能在线程池

中进行排队等待,当t1执行完毕后,把门打开,然后将钥匙还给CPU,然后t1线程或者消亡,或者进入阻塞状态,或者执行其他的过程

然后CPU再次把钥匙给在线程池中排队等待的线程,依次类推。。

(1)synchronized 同步函数

(2)synchronized 同步代码块

同步函数:

public class tickets {
public static void main(String[] args) {
sel s=new sel();
Thread t1=new Thread(s);
Thread t2=new Thread(s);
Thread t3=new Thread(s);
t1.start();
t2.start();
t3.start();
} }
class sel implements Runnable
{
private int num=100;
public synchronized void run()//同步函数的建立
{
while(true)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(num>0)
{
System.out.println(Thread.currentThread().getName()+"正在出售第"+num+"张票"+num--);
}else
{
break;
}
}
}
}

那么上面卖票中出现的问题就得到了解决,就不会出现一张票被卖多次,或者是出现卖第0张票的可能了。。

同步代码块:

public class tickets {
public static void main(String[] args) {
sel s=new sel();
Thread t1=new Thread(s);
Thread t2=new Thread(s);
Thread t3=new Thread(s);
t1.start();
t2.start();
t3.start();
} }
class sel implements Runnable
{
private int num=100;
public void run()//同步代码块的建立
{
synchronized(this)
{
while(true)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(num>0)
{
System.out.println(Thread.currentThread().getName()+"正在出售第"+num+"张票"+num--);
}else
{
break;
}
}
}
}
}

同步代码块的实现也可以避免线程的并发性,并且同步代码块比同步函数更具有优势,同步代码块的

效率也是比同步函数要高的。最重要的是同步代码块的好处在于:

      同步函数的锁只能是this,而同步代码块可以是任意一个obj对象,可以定义自己的类来定义自己的锁

同步代码块的速度也是比同步函数要更加快一些,应用的更加的广泛。。因此,在处理多线程安全问题的时候

最好使用同步代码块。。

  线程的常用方法

  1.start() 2.run() 3.sleep()4.isAlive()5.currentThread()6.interrupt()

前面的三个就不在进行介绍了。想必学习到了线程就知道这三个方法是什么意思了,isAlive()方法是判断

当前线程是否还活着。。currentThread()方法是获取当前执行线程的对象名,interrupt()方法是唤醒

休眠的线程。。下面举个例子。。。

/*
* 比如说张小帅正在睡觉,那么正是上课时间
* 张小帅睡觉线程正在执行,但是在上课时的
* 老师这个线程看到了张小帅睡觉线程,然后
* 直接叫醒了张小帅线程。。。
* */
public class Demo_1_1 {
public static void main(String[] args) {
ClassRoom room=new ClassRoom();
room.students.start();
room.teacher.start();
}
}
class ClassRoom implements Runnable
{
Thread students,teacher;
ClassRoom()
{
teacher=new Thread(this);
students=new Thread(this);
teacher.setName("张老师");
students.setName("张小帅");
}
public void run()
{
if(Thread.currentThread()==students)
{
System.out.println(Thread.currentThread().getName()+"正在睡觉,不听课");
try {
Thread.sleep(1000*60*60);
} catch (InterruptedException e) {
System.out.println(students.getName()+"被唤醒");
}
System.out.println("开始听课");
}
else if(Thread.currentThread()==teacher)
{
for(int i=1;i<=3;i++)
{
System.out.println("上课");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
students.interrupt();
}
}
}

顺便提一嘴。。一个已经运行的线程在没有进入死亡状态时,不要再次分配实体,由于线程的分配只能引用

最后一个实体,那么先前的实体就会成为垃圾,并且垃圾回收站不会去进行回收,因为JVM会认为那个垃圾

实体正在运行,如果突然使其中断,那么必然会导致设备的损坏。。。

比如说:

Thread thread=new Thread(target);

thread.start();

如果再次执行下面的语句。。。

thread=new Thread(target);那么原本的实体就会成为垃圾。。。

就好比下面这样。。。。


因此在写多线程的时候一定要避免这样的问题发生。。。

        

 

JAVA 多线程机制(二)的更多相关文章

  1. 简述Java多线程(二)

    Java多线程(二) 线程优先级 Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行. 优先级高的不一定先执行,大多数情况是这样的. 优 ...

  2. Java多线程(二)关于多线程的CPU密集型和IO密集型这件事

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  3. Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)

    一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会 ...

  4. java多线程系列(二)

    对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  5. java多线程系列(二)---对象变量并发访问

    对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  6. Java总结篇系列:Java多线程(二)

    本文承接上一篇文章<Java总结篇系列:Java多线程(一)>. 四.Java多线程的阻塞状态与线程控制 上文已经提到Java阻塞的几种具体类型.下面分别看下引起Java线程阻塞的主要方法 ...

  7. java多线程基础(二)--java多线程的基本使用

    java多线程的基本使用 在java中使用多线程,是通过继承Thread这个类或者实现Runnable这个接口或者实现Callable接口来完成多线程的. 下面是很简单的例子代码: package c ...

  8. (Java多线程系列二)线程间同步

    Java多线程间同步 1.什么是线程安全 通过一个案例了解线程安全 案例:需求现在有100张火车票,有两个窗口同时抢火车票,请使用多线程模拟抢票效果. 先来看一个线程不安全的例子 class Sell ...

  9. java多线程解读二(内存篇)

    线程的内存结构图 一.主内存与工作内存 1.Java内存模型的主要目标是定义程序中各个变量的访问规则.此处的变量与Java编程时所说的变量不一样,指包括了实例字段.静态字段和构成数组对象的元素,但是不 ...

随机推荐

  1. 【Android】5.8 滑动条(SeekBar)

    分类:C#.Android.VS2015: 创建日期:2016-02-07 一.简介 滑动条也叫拖动条(用户可拖动改变滑动条的值),比如可让用户调节音量大小.调节屏幕亮度.调节歌曲或视频当前播放的位置 ...

  2. ubantu 文件解压缩

    对于刚刚接触Linux的人来说,一定会给Linux下一大堆各式各样的文件名给搞晕.别个不说,单单就压缩文件为例,我们知道在Windows下最常见 的压缩文件就只有两种,一是,zip,另一个是.rar. ...

  3. 每日英语:Some Chinese Students Stay Home to Get Ahead

    Li Shan's oldest son was the perfect candidate to join the throngs of Chinese students studying abro ...

  4. hdoj2571 命运

    命运 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...

  5. 手动挡C1驾驶学车@长建驾校

    2015-11-01 下午取钱去长建驾校报名学车 4600(学费) + 100(暂住证) + 30(照片) + 10(体检) 2015-11-14 8:00-12:00 理论课2 光盘10  2015 ...

  6. Mybatis generator 自动生成代码

    开发项目的时候,表很多,是不可能一点点的自己去写xml ,dao文件的,这里就需要用到代码的自动生成工具了. 第一步:导入jar包,当然,这之前,基本环境,像mybatis,数据库之类的都得搭建好. ...

  7. Linux 网络子系统之NAPI书签

    只是一个书签 http://blog.csdn.net/ustc_dylan/article/details/6116334

  8. SpringBoot配置成Liunx服务

    spring boot 可以打包成可执行的脚本来启动,其原理是在打成包时,将shell脚本注入到jar包中 #参考:https://docs.spring.io/spring-boot/docs/1. ...

  9. Android ListView 长按列表弹出菜单

    Android ListView 长按列表弹出菜单 设置长按菜单 listView.setOnCreateContextMenuListener(new View.OnCreateContextMen ...

  10. firewalled centos7

    zone绑定网卡 firewall-cmd --zone=internal --add-interface=ens192 --permanent firewall-cmd --permanent -- ...