---------------------- android开发、java培训、期待与您交流! ----------------------
1、进程和线程有什么区别?
进程:正在执行的程序,线程是进程中的内容。每个应用程序中至少有一个线程,每一个进程执行都有一个执行顺序,该顺序是一个执行路径或者叫一个控制单元。进程就是用于定义空间标示空间,进程以启动在内存中就分配一块空间。
线程:就是进程中的一个独立的控制单元线程在控制着进程的执行,一个进程中至少有一个线程。所以说进程中包含线程,而线程决定进程的生命周期。
2、多线程存在的意义以及特性
多线程意义:多代码同时运行,提高效率。
特性:随机性,在某一时刻只能有一个线程在运行(多核除外)比如我们用电脑即能听歌,有能看视频,因为CPU在做着高速的切换,以达到看上去同时运行的效果,我们可以形象的把多线程运行行为看做是在抢夺CPU的执行权,谁抢到谁执行。
什么时候使用线程:当某些代码需要被同时执行时就用单独的线程进行封装。
3、创建线程方法之一(继承Thread类)
//创建线程 通过对API文档的查找发现java已经封装好对这类事物操作的对象 即Thread类
//创建线程的第一种方法 继承Thread类 并复写其中的run方法
步骤:1、定义一个类继承Thread
2、覆写Thread类中的run方法(将自定义的代码存储到在run方法中,让线程运行)
3、调用线程中的start方法,该方法有两个作用:启动线程和调用线程中run方法
eg:代码示例
class Demo extends Thread
{
public void run()
{
for(int i=0;i<100;i++)
{
System.out.println("第一个线程"+"-----"+i);
}
}
}
class ThreadDemo1
{
public static void main(String[] args)
{
//建立好一个对象就创建好一个线程
Demo d= new Demo();
//调用start方法 目的是开启线程并调用run方法
d.start();
for(int i=0;i<100;i++)
{
System.out.println("主线程main"+"-----"+i);
}
}
}
//运行结果是互相交错的 因为该程序中有两个线程 main线程和d线程 cup在这两个线程之间做着高速切换的动作
//多个线程在抢cpu资源
4、 为什么要覆盖run方法?
Thread类中用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法,也就是说Thread类中的run方法,是用于存储线程要运行的代码。(就是告诉线程你如果要干活,就干这一块别的不要管就行)。
6、创建线程方法之一(实现Runnable接口)
定义类声明实现Runnable接口,该类然后实现run方法,之后创建该类的实例,在创建Thread时将该类实例作为参数传递并启动线程。
步骤:1、定义类实现Runnable接口
2、覆盖Runnable接口中的run方法(将线程要运行的代码存放在run方法中)
3、通过Thread类建立线程对象
4、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
5、调用Thread类的start()方法,开启线程并调用Runnable接口子类的run方法
小知识:
为什么要将Runnable接口的子类对象传递给Thread的构造函数?
因为自定义的run方法所属对象时Runnable接口的子类对象,所以要让线程去执行制定对象的run方法,就必 须明确该run方法所属对象。
代码示例:
class Ticket implements Runnable
{
private int ticket = 100;
public void run()
{
while(true)
{
if(ticket>0)
{
System.out.println(Thread.currentThread().getName()+"----"+ ticket--);
//Thread类中有一个静态方法currentThread()获取当前线程对象getName()线程名字
}
}
}
}
class maiPiao
{
public static void main(String[] args)
{
//创建Runnable子类对象
Ticket t = new Ticket();
//通过Thread类 创建线程对象并且把Runnable接口子类对象作为参数传递给Thread类
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
//通过Thread对象调用start方法 开启线程并执行Runnable子类对象中的run方法
t1.start();
t2.start();
t3.start();
t4.start();
}
}
7、定义线程继承和实现的区别?
1、实现方式好处避免了单继承的局限性(建议使用实现方式)
2、继承Thread类线程代码存放在Thread子类run方法中
3、实现Runnable线程代码存放在接口子类的run方法中
8、线程安全问题
8.1 问题怎么产生的
在多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一条线程就参与进来执行,导致共享数据的错误。就比如火车站买票,火车票是共享数据而多个窗口是线程都在同时操作火车票。
8.2 怎么解决问题
思路:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中其他线程不可以参与执行、
Java对多线程安全问题提供了专业的解决方式就是同步代码块
格式:
synchronized(锁对象)
{
需要被同步的代码(正在操作共享数据的代码);
}
对象:对象如同锁,持有锁的线程才可以在同步中执行(火车卫生间),没有持有锁的线程及时有CPU执行权也进不去,因为没有获取锁,锁就相当于一个通行证 只有持有通行证的线程才可以进去。
8.3 同步的前提
1、必须有两个或两个以上的线程
2、必须是多线程使用同一个锁
3、必须保证同步中只能有一个线程
8.4 同步的利与弊
利:解决了多线程的安全问题,保证数据的准确性
弊:多个线程都需要判断锁较为消耗资源
8.5 针对多线程如何找问题
1、明确哪些代码是多线程运行的代码
2、明确共享数据
3、明确多线程运行代码中哪些语句是操作共享数据的
8.6 同步函数
就是把synchronized关键字作为修饰符放在函数上修饰,该函数就变成了同步函数。
eg:代码示例
public synchronized void add()
{
函数内部代码;
}
同步函数锁的知识点:同步函数需要被对象调用,那么函数都有一个所属对象的引用就是this,所以同步函数使用的锁是this。如果同步函数被静态所修饰后使用的锁是该类的字节码文件即:类名.class 因为静态进内存时内存中没有本类对象,但是一定有该类对应的字节码文件对象,所以被静态修饰的同步函数持有的锁是该类的字节码文件。
8.7单例设计模式(延迟加载 静态修饰同步函数 )
class Single
{
//私有构造函数
private Single(){}
//建立本类对象引用
private static Single s = null;
//提供公共访问方式 返回本类对象
public static Single getSingle()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
{
s= new Single();
}
}
}
return s;
}
}
8.8死锁
什么是死锁?
所谓死锁就是指两个以上的线程互相都有要求使用对方已经占有的资源而导致无法继续运
行的现象。就是同步中嵌套同步。
简单的一个死锁程序代码:
public class DeadLock
{
private static final Object obj1 = new Object();
private static final Object obj2 = new Object();
public class Run1 implements Runnable
{
String threadName = Thread.currentThread().getName();
public void run()
{
synchronized(obj1)
{
System.out.println(threadName+"进入同步块obj准备进入obj2");
synchronized(obj2)
{
System.out.println(threadName+"已经进入同步块obj2");
}
}
}
}
public class Run2 implements Runnable
{
String threadName = Thread.currentThread().getName();
public void run()
{
synchronized(obj2)
{
System.out.println(threadName+"进入同步块obj准备进入obj1");
synchronized(obj1)
{
System.out.println(threadName+"已经进入同步块obj1");
}
}
}
}
public static void main(String[] args)
{
Thread t1 = new Thread(new DeadLock().new Run1());
Thread t2 = new Thread(new DeadLock().new Run2());
t1.start();
t2.start();
}
}
9、线程之间的通讯
9.1 线程通讯概述
线程间通讯其实就是多个线程在操作同一资源,但操作的动作不同,例如两辆车一辆拉煤一辆送煤。当两个线程有安全问题是需要根据同步的前提进行判断(两个或两个以上的线程,锁必须相同,必须保证同步中只用一个线程在运行)
9.2 等待唤醒机制
wait( )你等会、notify( )你醒醒、notifyAll( )都醒了唤醒线程池中所有的线程,这三个方法全用在同步中,因为要对持有监视器(锁)的线程进行操作,所以要使用在同步中,因为只有同步才具有锁。
9.3为什么操作线程的放大都定义在Object中呢?
因为这些方法在操作同步中线程时都必须要标示他们所操作线程持有的锁。只有同一个锁上被等待的线程可以被同一个锁上的notify()唤醒,不可以对不同锁中的线程进行唤醒。也就是说等待和唤醒机制必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
10、JDK1.5版本后线程升级新特性
在JDK1.5版本后,线程出现了新特性,在java.util.concurrent.locks包中的Lock类,将同步synchronized替换成现实的Lock操作,将Object中的wait( )、notify( )、notifyAll( )替换成了Condition对象,该对象可以对Lock锁进行获取,在消费者生产者实例中,实现了只唤醒对方操作。
import java.util.concurrent.locks.*;
class chejian
{
private String name;
private int count=0;
private boolean flag=false;
Lock lock = new ReentrantLock();
Condition condition_sheng = lock.newCondition();
Condition condition_xiao = lock.newCondition();
public void set(String name)throws InterruptedException
{
lock.lock();//获取锁
try
{
while(flag)
condition_sheng.await();//线程等待
this.name = name;
count++;
System.out.println(name+"————生产者————"+count);
flag=true;
condition_xiao.signal();//唤醒线程
}
finally
{
lock.unlock();//释放锁
}
}
public void get()throws InterruptedException
{
lock.lock();//获取锁
try
{
while(!flag)
condition_xiao.await();//线程等待
System.out.println(name+"----消费者-----"+count);
flag=false;
condition_sheng.signal();//唤醒线程
}
finally
{
lock.unlock();//释放锁
}
}
}
//生产者线程
class sheng implements Runnable
{
chejian c;
sheng(chejian c)
{
this.c = c;
}
public void run()
{
while (true)
{
try
{
c.set("商品");
}
catch (InterruptedException e)
{
}
}
}
}
//消费线程
class xiao implements Runnable
{
chejian c;
xiao(chejian c)
{
this.c = c;
}
public void run()
{
while (true)
{
try
{
c.get();
}
catch (InterruptedException e)
{
}
}
}
}
class oneFive
{
public static void main(String[] args)
{
chejian c = new chejian();
xiao x = new xiao(c);
sheng s =new sheng(c);
Thread t1= new Thread(x);
Thread t2= new Thread(x);
Thread t3= new Thread(s);
Thread t4= new Thread(s);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
11、线程中的其他方法
线程停止原理:只有一种就是run方法结束,开启多线程运行,运行代码通常是循环结构,只要控制住循环就尅让run方法结束,也就是线程结束。
守护线程:setDaemon(boolean b) 传入true将该线程标记为守护线程或用户线程,该方法应该在启动线程前调用,即在start()前调用之前。当正在运行的线程都是守护线程时,Java 虚拟机退出。
eg:t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
join( ):等待该线程终止(抢夺主线程的CPU执行权),例如当A线程执行到了B线程的join()方法时,A就会等待,等B线程都执行完A才会执行,join ()可以用于临时加入线程执行。
·
优先级设置:setPriority(int newPriority)//线程优先级默认为5,优先级范围是1~10,即抢夺CPU执行的频率。
暂停线程:yield() 暂停当前正在执行的线程对象,并执行其他线程。
---------------------- android开发、java培训、期待与您交流! ----------------------
相关推荐
根据给定文件的信息,我们...通过以上知识点的学习,开发者可以深入理解Java多线程编程的核心概念和技术细节,为实际开发工作打下坚实的基础。同时,掌握这些高级并发技术对于构建高性能、高可靠性的应用系统至关重要。
黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.
黑马程序员__移动商城项目实战 包括黑马程序员乐淘商城实战和慕课React+Antd
公式指标,黑马起爆,有助于判断什么时候可以入手
本教程将聚焦于Java中的多线程技术,以“黑马程序员-java多线程技术01”为学习起点,探讨如何在Java中实现并管理线程。 首先,我们来理解什么是线程。线程是操作系统分配CPU时间的基本单元,一个进程中可以有多个...
在IT行业中,多线程是高性能程序设计的关键技术之一,特别是在服务器端开发、并发处理以及实时系统中。本文将深入探讨“多线程高新”这一主题,结合黑马程序员的课程内容,来阐述多线程的核心概念、优势、实现方式...
下面将详细介绍JavaWeb的基本概念、核心技术和黑马程序员源码在学习过程中的作用。 1. **JavaWeb基础** JavaWeb是基于Java技术构建Web应用的框架,它包括Servlet、JSP(JavaServer Pages)、JSTL(JavaServer ...
标题中的“heima_ugo_xiaochengxu_黑马训练营_微信小程序_小程序支付_VantWeapp商城”揭示了这是一个关于微信小程序开发的项目,由黑马训练营提供教学支持,特别关注了商城功能、微信登录和微信支付的集成,并且使用...
《黑马程序员_hibernate框架开发2016版讲义...通过对黑马程序员提供的这门课程的学习,开发者不仅能掌握Hibernate的核心概念和技术,还能提升在实际项目中的数据库操作效率,为构建高效、稳定的Java应用打下坚实基础。
黑马程序员_毕向东_Java基础视频教程第18天-14-IO流(拷贝文本文件图例).zip
【标题】"传智播客_黑马_品优购_2018"指的是一个由传智播客和黑马程序员联合推出的2018年品优购相关的IT培训课程资源。这个课程可能涵盖了电子商务、互联网产品开发、运营等多个方面,旨在帮助学员掌握最新的技术和...
【青橙电商前台开发02】课程主要涵盖了电商网站前端开发的相关知识,是黑马教育机构...同时,黑马青橙电商的课程通常以实战为导向,让你在实践中学习和成长,所以“好好看吧”,这对你在电商领域的职业发展将大有裨益。
暗示这门课程可能包含一系列视频教程,首个文件"01_黑马程序员_张孝祥_Java基础加强_课程价值与目标介绍.avi"很可能是课程的开篇,详细阐述了课程的价值、目标以及教学计划,帮助学员了解学习路径和预期收获。...
重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip重现黑马评论项目_ hmdp.zip
通过这个“黑马旅游网项目”,学习者可以系统地了解和掌握Java Web开发的基础技能,为后续更高级的Web开发技术打下坚实基础。这个项目不仅提供了理论知识,还将通过实际操作帮助学习者提升解决问题的能力,更好地...
黑马程序员_ibatis视频教程,仅供参考学习,有需要的可以下载,本人有全栈开发工程师各种学习技术视频教程及本档,有需要的可以留言或到本人账号下载
黑马程序员_JDBC视频教程,仅供参考学习,有需要的可以下载,本人有全栈开发工程师各种学习技术视频教程及本档,有需要的可以留言或到本人账号下载
3. CSS布局:包括定位(static、relative、absolute、fixed),Flexbox(弹性盒子布局)和Grid(网格布局)等现代CSS布局技术,用于创建复杂的网页布局。 4. 页面响应式设计:如何使用媒体查询(@media)让网页在...
总结来说,"黑马程序员_毕向东_Java基础源码.rar"为初学者提供了一个深入学习Java编程的宝贵平台。通过学习和实践这些源代码,不仅可以巩固Java基础知识,还能培养良好的编程习惯和思维模式,为成为专业Java开发者...
day05_异常,线程 day06_线程、同步 day07_等待与唤醒案例、线程池、Lambda表达式 day08_File类、递归 day09_字节流、字符流 day10_缓冲流、转换流、序列化流、Files day11_网络编程 day12_函数式接口 day13_Stream...