黑马程序员——多线程

------- android培训java培训、期待与您交流! ----------

导图


一、概述

1、进程

是一个正在执行中的程序。每一个程序执行都有一个执行顺序。该顺序是一个路径,或者叫一个控制单元。

2、线程:就是进程中一个独立的控制单元。线程序控制着进程执行。

一个进程至少有一个线程(多线程)。java启动时会有一个进程java.exe该进程中至少有一个线程负责java程序的执行而且这个线程运行的代码存在于main方法中该线程称之为主线程

扩展:其实更细节说明jvm 启动不止一个线程,还有负责垃圾回收的机制线程。

二、多线程的创建

1.如何在定义的代码中,自定义一个线程呢?

通过APi的查找,java已经提供了对线程事物的描述,就thread类。创建线程的第一种方法,就是继承Thread类。

步骤:

1.定义继承类Thread

2.复写Thread类中的run方法

3.调用线程的start方法。

该方法两个作用:启动线程调用run方法

 

三、运行

发现运行的每一次一结果都不一样因为多个线程执行获取CPU执行权,cpu执行到谁,谁就运行。明确一点,在某一时刻,只有一个程序在运行(多核除外)。CPU在做着快速切换,以达到看法上是在同时运行的效果。我们可以形像看成多线程运行在抢夺CPU执行权。这就是多线程的一个特性:随机性,随抢到随执行,至于执行多长时间,由cpu决定。

进程运行有五种状态:被创建、运行、冻结、阻塞、消亡。它们之间的转化关系如下:


线程都有自己的名称 Thread-编号从0开始。用static Thread.currentThread();可以获取当前对象;用getName();获取线程名称;设置线程名称用etName或者构造函数。

四、Runable

创建线程有两种方式,前面已经提到第一种方法继承Thread类形式创建。那么第二种方法就是实现Runnable接口。步骤如下:

1、     定义类实现Runnable接口;

2、     覆盖Runnable中的run方法,将线程要运行的代码存放在该run方法中;

3、     通过Thread类创建对象;

4、     将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。为什么要将Runnable接口的子类对象传给Runnable的构造函数呢?因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定对象的run方法,就必须明确run方法所属对象。

这种现实方式和第一种继承方式有什么区别呢?

避免了单继承的局限性,在定义线程时,建议使用实现方式。

在同步函数被静态和,使用的锁是什么呢?

通过验证,发现不再是this。因为静态方法中不可以定义this。静态进内存时,内存中没有本类对象,但是一定有该类的字节码文件对象(类名.class)。该对象的类型是class。

五、安全问题

1、出现问题的原因

当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另个线程参与进来执行,导致共享数据出错。

2、解决办法

对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他程序不可以参与执行。Java对于多线程的安全问题提供了专业的解决方式就是同步代码块,格式如下:

Synchronized(对象)

{

需要同步的代码

}

对象如同锁一样,持有锁的进程可以在同步中执行,没有持有锁的程序即使获取CPU的执行权,也进不去,因为没有获取锁。

那么如何寻找其中的安全问题呢?

首先要明确哪些代码是多进程运行代码;其次,明确共享数据;然后明确多线程运行代码中哪些语句操作共享数据。

进程安全问题当中除了有以上情况之外还有一种情况叫死锁。死锁就是同步中嵌套同步,而所持有的锁不一样的情况。死锁在实际开发中要避免。

六、通信

在线程通信中有wait、notify、notifyAll方法使用在同步中,因为要对持有监视器(锁)的进

为什么这些方法在操作同步线程时,都必须要标识它们所操作线程持有的锁,只有同一个锁上的线程才可以被同一个锁上的notify唤醒。不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在objec类中

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马程序员线程练习题主要包括两个问题。第一个问题是如何控制四个线程在打印log之前能够同时开始等待1秒钟。一种解决思路是在线程的run方法中调用parseLog方法,并使用Thread.sleep方法让线程等待1秒钟。另一种解决思路是使用线程池,将线程数量固定为4个,并将每个调用parseLog方法的语句封装为一个Runnable对象,然后提交到线程池中。这样可以实现一秒钟打印4行日志,4秒钟打印16条日志的需求。 第二个问题是如何修改代码,使得几个线程调用TestDo.doSome(key, value)方法时,如果传递进去的key相等(equals比较为true),则这几个线程应互斥排队输出结果。一种解决方法是使用synchronized关键字来实现线程的互斥排队输出。通过给TestDo.doSome方法添加synchronized关键字,可以确保同一时间只有一个线程能够执行该方法,从而实现线程的互斥输出。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [黑马程序员——多线程10:多线程相关练习](https://blog.csdn.net/axr1985lazy/article/details/48186039)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值