- 浏览: 55422 次
- 性别:
- 来自: 郑州
文章分类
最新评论
-
咖啡骑士:
亲测有效,谢谢了,转一下哦
mybatis创建oracle触发器的问题 -
ocaicai:
我遇到的问题是:批量更新1000条数据,居然使用了13秒,在百 ...
jdbcTemplate.batchUpdate没有批量执行
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线程执行完以后,主线程才会执行,此时主线程就处于冻结状态。
一般使用情况:当在线程执行过程中,需要一个运算结果时,可以通过加入一个临时线程,将该结果进行运算,这时需要结果的线程处于冻结状态,当加入的线程执行完,该线程在继续执行。
什么是进程?{
当前正在运行的程序。
代表一个应用程序在内存中的执行区域。
}
什么是线程(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线程执行完以后,主线程才会执行,此时主线程就处于冻结状态。
一般使用情况:当在线程执行过程中,需要一个运算结果时,可以通过加入一个临时线程,将该结果进行运算,这时需要结果的线程处于冻结状态,当加入的线程执行完,该线程在继续执行。
发表评论
-
javaIO包
2014-02-26 14:30 759Java IO流: 流是一组有 ... -
java集合
2014-02-26 14:28 1378Java中的集合: 为什么出现集合类? 面向对象语言对事物的体 ... -
java包
2014-01-26 17:59 715Java包:(package) 1.对 ... -
java内部类
2014-01-26 17:58 640Java内部类: 内部类:内置类,嵌套类。 将类定义在另一 ... -
java语法
2014-01-26 17:57 6351.java类命名规则? java中的关键字不能够作为类名, ... -
java异常
2014-01-26 17:55 736Java异常 什么是异常? ... -
java面向对象
2014-01-19 20:24 639什么是面向对象? 面向 ... -
java数组
2014-01-19 20:22 637什么是数组? 就是同一种类型数据的集合,其实就是 一个容器。 ... -
java中的运算符
2014-01-19 20:14 511Java运算符? Java中进行运算时所需要运用到的一些符号。 ... -
java中的流程控制
2014-01-19 20:12 689Java中有四类流程控制 判断结构 选择结构 循环结构 顺序结 ... -
java应用程序与数据库的连接
2013-05-30 02:31 749java应用程序与数据库的连接 Java数据库连接,(Jav ... -
java网络编程
2013-05-29 17:07 633java网络编程如果在一台机器上可以用到一个回文地址做测试,1 ... -
java图的邻接矩阵的表示和实现
2013-05-22 21:32 3888邻接矩阵表示的带权图。。。 首先创建了一个带权值的边类,在图中 ... -
线程通讯问题
2013-05-15 17:01 633//有一个数据存储空间,划分为两部分,一部分用于存储人的姓 ... -
java线程锁定当前对象
2013-05-12 15:44 686java实现线程同步,如果有多个线程同时进行,那么程序很有可能 ... -
关于127.0.0.1 IP地址
2013-04-11 11:32 1440回送地址:127.0.0.1。一般用于测试使用。例如:ping ...
相关推荐
Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...
Java多线程读大文件 java多线程写文件:多线程往队列中写入数据
java多线程PPT 多线程基本概念 创建线程的方式 线程的挂起与唤醒 多线程问题
一个java 多线程操作数据库应用程序!!!
java多线程经典案例,线程同步、线程通信、线程阻塞等经典案例
《Java多线程编程核心技术》建议猿友们读两遍,因为其写得没有那么抽象,第一遍有些概念不是很理解,可以先跳过并记录起来,第一遍阅读的目的主要是了解整个架构。第二遍再慢慢品味,并贯穿全部是指点来思考,并将...
Java多线程编程实战指南(核心篇) 高清pdf带目录 随着现代处理器的生产工艺从提升处理器主频频率转向多核化,即在一块芯片上集成多个处理器内核(Core),多核处理器(Multicore Processor)离我们越来越近了――如今...
该文档总结了Java多线程相关的知识点,分享给大家,简单易懂!
详细的讲解了java多线程的原理,并配有代码进行实战,适合java初学者和想对多线程有进一步了解的人。
一张图方便理解和掌握java 多线程之间通信的实质 java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,...
java多线程处理数据库数据,使用并发包,无框架,可批量处数据库数据,进行增删改。。等等操作。
java多线程,对多线程,线程池进行封装,方便使用
现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。 线程是指进程中的一个执行流程,一个进程中可以运行多个线程。...本文档提供Java多线程编程经验,方便广大Java爱好者研究学习Java多线程
java多线程处理大数据,可根据配置的线程数,任务去调度处理
java多线程并发的在新窗口
Java多线程机制 9.1 Java中的线程 9.2 Thread的子类创建线程 9.3 使用Runable接口 9.4 线程的常用方法 9.5 GUI线程 9.6 线程同步 9.7 在同步方法中使用wait()、notify 和notifyAll()方法 9.8 挂起、恢复和终止线程 ...
资深Java专家10年经验总结,全程案例式讲解,首本全面介绍Java多线程编程技术的专著 结合大量实例,全面讲解Java多线程编程中的并发访问、线程间通信、锁等最难突破的核心技术与应用实践 Java多线程无处不在,如...
java多线程实现大批量数据切分成指定份数的数据,然后多线程处理入库或者导出,线程的个数和每份数据的数量都可以控制
java多线程并发查询数据库,使用线程池控制分页,并发查询。
java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号 java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号