主要内容

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. PHP利用MySQL保存session(php5.4之前的处理)

    简介 使用MySQL保存session,需要保存三个关键性的数据:session id.session数据.session生命期. 考虑到session的使用方式,没必要使用InnoDB引擎,MyIS ...

  2. Linux下hosts、host.conf、resolv.conf的区别

    /etc/resolv.conf 该文件是DNS域名解析的配置文件,它的格式很简单,每行以一个关键字开头,后接配置参数.resolv.conf的关键字主要有四个,分别是:nameserver   #定 ...

  3. Perl的新特性开启

    1.perl自从5.8开始,新特性需要开启才可以使用,默认只是5.8版本,而不管当前你使用的是那个版本. 2.开启新特性,当然最高可用版本是你实际安装的版本,假设你安装的是v5.26版 ; #或者这样 ...

  4. 【Android】4.1 UI设计器

    分类:C#.Android.VS2015:创建日期:2016-02-06 开发人员可以用以下两种方式声明UI:一是通过.xml文件(不带预览界面)或者.axml文件(带预览界面)来描述:二是用C#代码 ...

  5. 无线路由器硬件配置參数 NetGear篇

    NetGear     WNDR4500(号称地球上最强的无线路由器)    450Mbps+450Mbps          京东¥1399 0MHz.配备了128MB的内存和128MB的闪存,再以 ...

  6. CDN技术详解笔记

    1.影响网络传输的四个因素(1)“第一公里”:网站服务器接入互联网的链路所能提供的带宽.(2)“最后一公里”:用户接入带宽.(3)对等互联关口:不同网络之间的互联互通带宽.(4)长途骨干传输:首先是长 ...

  7. spark内存概述

    转自:https://github.com/jacksu/utils4s/blob/master/spark-knowledge/md/spark%E5%86%85%E5%AD%98%E6%A6%82 ...

  8. 20个可能你不知道Linux网路工具

    如果要在你的系统上监控网络,那么使用命令行工具是非常实用的,并且对于 Linux 用户来说,有着许许多多现成的工具可以使用,如: nethogs, ntopng, nload, iftop, iptr ...

  9. Qt入门-layout布局

    开发一个图形界面应用程序,界面的布局影响到界面的美观.在设计一个界面之前,应该考虑到开发的界面可能给不用的用户使用,而用户的屏幕大小.纵横比例.分辨率可能不同,界面还可能是可缩放的,程序应该可以适应这 ...

  10. Sql Server连接字符串

    SQL Server .NET Data Provider 连接字符串包含一个由一些属性名/值对组成的集合.每一个属性/值对都由分号隔开.          PropertyName1=Value1; ...