`
javawangzilong
  • 浏览: 56871 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

java多线程

阅读更多
Java多线程:

什么是进程?{
当前正在运行的程序。
代表一个应用程序在内存中的执行区域。
}


什么是线程(FlashGet)?{
是进程中的一个执行控制单元,执行路径。
(执行空间代码的执行者)
}

一个进程中至少有一个线程在负责控制程序的执行。
一个进程中如果只有一个执行路径,这个程序成为单线程程序。
一个进程中如果有多个执行路径时,这个程序成为多线程程序。

多线程的出现:可以有多条执行路径。让多部分代码可以完成同时执行。以提高效率。本身也是对问题的一种解决方案,比如图形界面的多个小程序同时执行。比如360,迅雷

Jvm启动是单线程还是多线程?{

Jvm的启动就是多线程程序。
其中有一个程序负责从主函数开始执行,并控制程序运行的流程。
同时为了提高效率,还启动了另一个控制单元(执行路径)专门负责堆内存中的垃圾回收,在程序正常执行的过程中,如果出现了垃圾,这时另一个负责收垃圾的线程会在不定时的时间内进行垃圾的处理。这两个程序是同时执行的。

}

负责执行正常代码的线程,称为主线程,该线程执行的代码都存放于主函数中。
负责收垃圾代码的线程,称为垃圾回收线程。该线程要执行的代码在finallize中。

如何在java中创建一个线程?{

其实java中对线程这类事物已经进行了描述,并提供了相对应的对象。
这个对象就是java.lang.Thread。

创建线程的两种方式
1.继承Thread类。
  步骤:
  1.定义类继承Thread
  2.覆盖Thread类中run方法()
  3.创建Thread类中的子类对象创建线程。
  4.调用Thread类中的start方法开启线程,并执行子类中的run方法
  特点:
  1,当类去描述事物,事物中有属性和行为。如果行为中有部分代码需要被多线程 所执,行,同时还在操作属性。就需要该类继承Thread类,产生该类的对象作为线 程对象。可是这样会导致每一个对象中都会存储一份属性数据。
  无法在多个线程中共享数据,加上静态,虽然实现了共享,但是生命周期过长。
2.如果一个类明确了自己的父类,那么就不可以继承Thread。因为java不允许类的多继承。

2.实现runnable接口。
  步骤:
1.定义类实现Runnable接口。
2.覆盖接口中的run方法。(将多线程要运行的代码定义在方法中)
3.通过Thread类创建线程对象,并将实现了runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
(为什么非要被Runnable接口的子类对象传递给你Thread类的构造函数呢?
  是因为线程对象在建立时,必须要明确自己要运行的run方法,而这个run方 法定义在了Runnable接口的子类中,所以要将该run方法所属的对象传递给 Thread类的构造函数。让线程对象建立,就知道运行那个run方法。

4.调用Thread类中的start方法,开启线程,并执行Runnable接口子类中的run方法。
特点:
  1.描述事物的类中封装了属性和行为,如果有部分代码需要被多线程所执行,
  同时还在操作属性,那么可以通过实现Runnable接口的方式。因为该方式是定义一个Runnable接口的子类对象,可以被多个线程所操作。实现了数据共享。
2.实现了Runnable接口的好处,避免了单继承的局限性。一个类如果已经有了自己的父类,不可以继承Thread类。但是该类中还有需要被多线程执行的代码。这时就可以通过在该类上功能扩展的形式。实现一个Runnable接口。

  所以创建线程时,尽量使用第二种方法。
  
创建线程的两种方式区别?



(为什么要覆盖run?
直接建立Thread类对象即可,并开启线程执行就可以了,但是虽然线程执行了,可是执行的代码是该线程默认的代码,该代码就存放在run方法中。
可是定义线程的目的是为了执行自定义的代码。
而线程的运行代码都存储在run方法中,所以只有覆盖了run方法,才可以运行自定义的内容。想要覆盖,必须要先继承。

主线程运行的代码都在main函数中,自定义的代码都在run方法中。
)

(
**
直接创建Thread类的子类对象就是创建了一个线程,如果直接调用该对象的方法。这时,底层资源并没有完成线程的创建和执行,仅仅是简单的调用对象的方法。
在内存中其实:1.堆内存中产生了一个对象,2.需要调用底层资源去创建执行路径

如果想要开启线程:需要调用start方法,该方法做了两件事
1.开启线程
2.调用线程的run方法
)
}


当创建了两个线程后的d1,d2后,这时程序就有了三个线程在同时执行。
当主函数执行完d1.start(),d2.start()后,这时三个线程同时打印,结果比较杂乱。
这是因为线程的随机性造成的。
随机性的原理是:windows中的多任务同时执行,其实就是多个应用程序在同时执行。
而每一个应用程序都有线程来负责控制的。所以window就是一个多线程的操作系统,那么cpu是负责提供程序运算的设备。cpu在某一时刻只能执行一个程序,所谓的多任务执行就多个应用程序在执行,其实是cpu通过快速切换来完成的。 只是感觉上是同时而已。

能不能真正意义上的同时执行?{
可以,多个cpu,就是现在的多核。
}

线程中的方法:
多线程的创建,为了对各个线程进行标示,系统会自动对各个线程起一个名字(thread--)
Static Thread currentThread() 获取到当前线程
String getName() 得到当前线程的名称
Vodi setName() 重新设置线程的名称

如何获取到主线程?
可以通过Thread类中的一个方法:currentThread返回当前正在执行的线程对象。
主线程的名字叫main--


在线程被创建后,可以分为临时阻塞状态,运行状态,冻结状态,消亡状态。
如果有三个线程A,B,C;当三个线程都调用start方法之后,三个线程都具备了执行资格,
处于临时阻塞状态。
当某一个线程A正在被CPU处理,说明A处于运行状态,即具备了资格,也具备了CPU的执行权。
而B,C处于临时阻塞状态,当CPU切换到B线程时,B就具备执行权,这时,A,C就处于临时阻塞状态,只具备执行资格,不具备执行权。

当一个线程被cpu执行具备了执行权,就到了运行状态,当cpu切换到其他线程开始执行的时候,刚才的线程就失去了执行权,回到了临时阻塞状态。
当一个线程调用了sleep,wait方法后,就释放了cpu的执行权,并释放了执行资格。
冻结状态结束后,表示线程重新具备了执行资格,但是不一定立刻具备执行权。
比如睡眠时间到,或者用notify方法唤醒线程。

当一个线程执行完就到了消亡状态,也可以调用stop方法让线程进行消亡。




线程安全问题:(因为线程的随机性,有可能会导致多线程在操作数据时发生数据错误的情况)
线程安全问题产生的原因:
当线程多条代码在操作同一个共享数据时,一个线程将部分代码执行完,还没有继续其他代码时,被另一个线程获取cpu执行权,这时,共享数据操作就有可能出现数据错误。
简单说:多条操作功能数据的代码被多个线程分开执行造成的。
安全问题涉及的内容:
共享数据。
是否被多条语句操作。
这也是判断多线程程序是否存在安全隐患的依据。

解决安全问题的方式:
  Java中提供了一个同步机制。
  解决原理:让多条操作共享数据的代码在某一时间段,被一个线程执行完,在执行过程中,其他线程不可以参与运算。
  
  同步格式:
  同步代码块:
  Synchronized(对象){
  需要被同步的代码
  }
  
  同步的原理:通过一个对象锁,将多条操作共享数据的代码进行了封装并加锁。只有持有这个锁的线程才有机会进入同步中的去执行,在执行期间,即使其他线程获取到执行权。因为没有获取到锁,所以只能在外面等。只有同步中的线程执行完同步代码块中的代码,
  出同步代码块时,才会释放这个锁,那么其他程序线程才有机会去获取这个锁,并只能有一个获取到而且进入到同步中。
  
  同步的好处:
  同步的出现解决了多线程的安全问题
  同步的弊端:
  因为多个线程每次都要判断这个锁,所以效率会降低。
  
  加入了同步,安全问题有可能依然存在,
  因为同步是有前提的:
  1,同步必须是有两个或两个以上的线程才需要同步
  2,必须要保证多个线程使用的是同一个锁,才可以实现多个线程被同步。
  如果出现加上同步,安全问题依然存在,就按照两个前提来排查问题。

如何查看程序中有无线程安全隐患?{
1,查看线程代码中是否有共享数据。
2,这个共享数据有没有被多条语句所操作。
}

同步代码块时用于封装代码的,函数也用于封装代码,不同之处是同步带有
锁机制。那么如果让函数这个封装体具备同步的特性。就可以取代同步代码块。
同步函数:就是在函数上加上synchronized关键字。Public synchronized void add();

那么同步函数用的哪个锁?{
  在同步代码块中用的是任意一个对象用来加锁,而同步函数中的锁用的是当前对象
  ,也就是this
}

同步函数和同步代码块的区别:{
同步代码块使用的锁可以是任意对象,
同步函数使用的锁是固定对象,this
所以一般定义同步时,建议使用同步代码块。
}

静态同步函数用的是哪个锁?{
  静态同步函数使用的锁不是this,
  因为静态函数中不可以定义this。
  
  静态随着类的加载而加载,这时有可能内容还没有该类的对象。
  但是一个类加载进内存,会先将这个类对应的字节码文件封装成对象,
  该对象的表示方式  类名.class 代表一个类字节码文件对象,
  该对象在内存是唯一的。
  
  静态同步函数使用的锁就是,该类对应的字节码文件对象,也就是类名.class
}

死锁:
死锁经常出现的状况为:同步嵌套。

class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+"...if......locka");
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"...if......lockb");

}
}
}
}
else
{
while(true)
{
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"...else..........lockb");
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+"...else..........locka");

}
}
}
}
}

}

class MyLock
{
public static Object locka = new Object();
public static Object lockb = new Object();
}


class DeadLockTest
{
public static void main(String[] args)
{
Test t1 = new Test(true);
Test t2 = new Test(false);

Thread th1 = new Thread(t1,"小强");
Thread th2 = new Thread(t2,"旺财");

th1.start();
th2.start();
}
}

线程间通信:
Wait():让线程等待,将线程存储到一个线程池中。
Notify():唤醒被等待的线程,通常都唤醒线程池中的第一个,让被唤醒的线程处于临时阻塞状态。
notifyAll():唤醒所有的等待线程,将线程池中的所有线程都唤醒,让他们从冻结状态转到临时阻塞状态。

这三个方法用于操作线程,但是都定义在Object类中:
因为,这三个方法在使用的时候,都需要定义在同步中,要明确这些方法所操作的线程所属于锁。例如A锁被wait的线程,只能被A锁的notify方法唤醒。
所以必须要表示wait,notify方法所属的锁对象,而锁对象可以是任意的对象。可以被任意的对象调用的方法肯定定义在Object类中。

**等待唤醒机制,通常都用在同步中,因为需要锁的支持。而且必须要明确wait,notify锁作用的锁对象。

在java.util.concurren.locks包中提供了一个接口Lock。代替了synchronized。
Synchronized使用的隐式锁
Lock使用的是显示的锁。
Lock()获取锁
Unlock()释放锁

还有一个对象Condition。
该对象的出现替代了Object中的wait,notify,notifyAll这些操作监视器的方法
替代后await,signal,signalAll。

**新功能最大的好处就是在一个lock锁上可以添加多组监视器对象,这样就可以实现
本方只唤醒对方的现象。

Sleep和wait的区别?{
1,sleep方法必须指定时间
2,wait方法有重载形式,可以指定时间,也可以不指定

对于执行权和锁的操作:
1,sleep():释放执行权,不释放锁,因为肯定能恢复到临时阻塞状态
2,wait():释放执行权,释放锁,因为wait不释放锁,如果没有时间指定,那么其他线程都进行不了同步中,无法将其唤醒。

(同步中可以有多个存活的线程,但是只能有一个执行同步的代码,因为只有一个线程会持有同步锁,只有当该线程释放了锁,其他线程才有机会获取到锁,而且只能用一个线程获取到锁,继续执行。)
}

如何让线程停止?
1,使用Thread类中的stop方法。(强制结束,已过时)
2,线程执行的代码结束。

通常定义线程代码都有循环,因为需要单独开辟一个执行路径去重复很多事情。既然有循环,控制住循环,就可以结束run方法。
定义标记可以结束线程,但是如果线程在运行过程中处于了冻结状态,没有执行到标记,这时,可以通过Thread类中的interrupt方法中断线程的冻结状态。强制让其恢复到运行状态中来,就可以有机会执行标记,但是这种强制动作会发生异常。

setDeamo(boolean):可以将线程标记为后台线程。
线程分前台和后台两种。运行方式都一样都会获取cpu的执行权执行
不同的在于,结束的方式不同。
前台线程只有run方法结束,才结束。
后台线程,run方法结束,结束,还有,如果run方法没结束,而前台线程都结束了,后台线程也结束。
所以一个进程是否结束参考的是,是否还有前台线程存活,如果前台线程都结束了,那么进程也就结束了。


当有了join方法以后,该t1线程会全部执行完,其他线程才可以执行。
Join:临时加入一个线程进行执行。
例如,当主线程获取到了cpu的执行权,执行时,执行到了A线程的join方法。
这时就知道A线程要加入进来执行,那么A执行就需要cpu的执行权。而这时cpu的执行权在主线程持有,主线程会释放自己的执行权。让A线程进行执行,只有等A线程执行完以后,主线程才会执行,此时主线程就处于冻结状态。

一般使用情况:当在线程执行过程中,需要一个运算结果时,可以通过加入一个临时线程,将该结果进行运算,这时需要结果的线程处于冻结状态,当加入的线程执行完,该线程在继续执行。


分享到:
评论

相关推荐

    Java多线程知识点总结

    Java多线程是Java编程语言中一个非常重要的概念,它允许开发者在一个程序中创建多个执行线程并行运行,以提高程序的执行效率和响应速度。在Java中,线程的生命周期包含五个基本状态,分别是新建状态(New)、就绪...

    java 多线程操作数据库

    ### Java多线程操作数据库:深入解析与应用 在当今高度并发的应用环境中,Java多线程技术被广泛应用于处理数据库操作,以提升系统的响应速度和处理能力。本文将基于一个具体的Java多线程操作数据库的应用程序,深入...

    Java多线程设计模式上传文件

    Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...

    java多线程经典案例

    Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,极大地提升了程序的效率和性能。在Java中,实现多线程有两种主要方式:通过实现Runnable接口或者继承Thread类。本案例将深入探讨Java多线程中的关键...

    java多线程Demo

    Java多线程是Java编程中的一个重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应速度。在Java中,实现多线程有两种主要方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当我们创建一个新...

    java多线程的讲解和实战

    Java多线程是Java编程中的重要概念,尤其在如今的多核处理器环境下,理解并熟练掌握多线程技术对于提高程序性能和响应速度至关重要。本资料详细讲解了Java多线程的原理,并提供了丰富的实战代码,非常适合Java初学者...

    java多线程分页查询

    ### Java多线程分页查询知识点详解 #### 一、背景与需求分析 在实际的软件开发过程中,尤其是在处理大量数据时,如何高效地进行数据查询成为了一个关键问题。例如,在一个用户众多的社交平台上,当用户需要查看...

    汪文君JAVA多线程编程实战(完整不加密)

    《汪文君JAVA多线程编程实战》是一本专注于Java多线程编程的实战教程,由知名讲师汪文君倾力打造。这本书旨在帮助Java开发者深入理解和熟练掌握多线程编程技术,提升软件开发的效率和质量。在Java平台中,多线程是...

    java多线程ppt

    java多线程PPT 多线程基本概念 创建线程的方式 线程的挂起与唤醒 多线程问题

    java多线程读取文件

    Java多线程读大文件 java多线程写文件:多线程往队列中写入数据

    Java多线程机制(讲述java里面与多线程有关的函数)

    Java多线程机制是Java编程中至关重要的一部分,它允许程序同时执行多个任务,提升应用程序的效率和响应性。以下是对各个知识点的详细说明: 9.1 Java中的线程: Java程序中的线程是在操作系统级别的线程基础上进行...

    深入浅出 Java 多线程.pdf

    在本文中,我们将深入浅出Java多线程编程的世界,探索多线程编程的基本概念、多线程编程的优点、多线程编程的缺点、多线程编程的应用场景、多线程编程的实现方法等内容。 一、多线程编程的基本概念 多线程编程是指...

    java 多线程并发实例

    在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...

    JAVAJAVA多线程教学演示系统论文

    《JAVA多线程教学演示系统》是一篇深入探讨JAVA多线程编程的论文,它针对教育领域中的教学需求,提供了一种生动、直观的演示方式,帮助学生更好地理解和掌握多线程技术。这篇论文的核心内容可能包括以下几个方面: ...

    java多线程实现大批量数据导入源码

    本项目以"java多线程实现大批量数据导入源码"为题,旨在通过多线程策略将大量数据切分,并进行并行处理,以提高数据处理速度。 首先,我们需要理解Java中的线程机制。Java通过`Thread`类来创建和管理线程。每个线程...

    java多线程查询数据库

    综上所述,"java多线程查询数据库"是一个涉及多线程技术、线程池管理、并发控制、分页查询等多个方面的复杂问题。通过理解和掌握这些知识点,我们可以有效地提高数据库操作的效率和系统的响应速度。

    java 多线程编程实战指南(核心 + 设计模式 完整版)

    《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...

    JAVA多线程编程技术PDF

    这份“JAVA多线程编程技术PDF”是学习和掌握这一领域的经典资料,涵盖了多线程的全部知识点。 首先,多线程的核心概念包括线程的创建与启动。在Java中,可以通过实现Runnable接口或继承Thread类来创建线程。创建后...

    Java多线程编程核心技术_完整版_java_

    Java多线程编程是Java开发中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过继承Thread类或实现Runnable接口来实现。本教程《Java多线程编程核心技术》将...

    Java多线程编程实战指南(核心篇)

    Java多线程编程实战指南(核心篇) 高清pdf带目录 随着现代处理器的生产工艺从提升处理器主频频率转向多核化,即在一块芯片上集成多个处理器内核(Core),多核处理器(Multicore Processor)离我们越来越近了――如今...

Global site tag (gtag.js) - Google Analytics