黑马程序员_java基础笔记(04)...多线程
2015-01-09 20:51
260 查看
多线程。第一重点:创建线程的两种方式。第二重点:同步的所有特性
进程:正在执行的程序。
线程:是进程中用于控制程序执行的控制单元(执行路径,执行情景)进程中至少有一个线程。
对于JVM,启动时,有两个线程:jvm的主线程。jvm的垃圾回收线程。
第一重点:创建线程的两种方式
如何在程序中自定义线程?
Java给我们提供了对象线程这类事物的描述。该类是Thread
该类中定义了,
创建线程对象的方法(构造函数).
提供了要被线程执行的代码存储的位置run()
开启线程运行的方法start()
还有一些其他的方法用于操作线程:
staticThreadcurrentThead()//获取当前线程对象。
getName()://返回该线程的名称。
staticvoidsleep(time)throwsInterruptedException:
join()方法//等待该线程终止。
创建线程的第一种方式是:继承Thread类。
原因:要覆盖run方法,定义线程要运行的代码。
步骤:
1,继承Thread类。
2,覆盖run方法。将线程要运行的代码定义其中。
3,创建Thread类的子类对象,其实就是在创建线程,调用start方法。
示例:多个窗口同时买票1,继承Thread类
classTicketextends
Thread{
//
static让四个卖票窗口共享100票
privatestaticinttick=100;
//覆盖run方法
publicvoidrun(){
while(true){
if(tick>0){
System.out.println(Thread.currentThread().getName()+"....sale:"+tick——);
}
}
}
}
classTicketDemo{
publicstaticvoidmain(String[]args){
Tickett1=newTicket();
Tickett2=newTicket();
Tickett3=newTicket();
Tickett4=newTicket();
//调用start方法
t1.start();
t2.start();
t3.start();
t4.start();
}
}
创建线程的第二种方式:实现Runnable接口。
如果自定义类中有多线程要运行的代码。但是该类有自己的父类。那么就不可以在继承Thread。Java给我们提供了一个规则。Runnable接口。
如果自定义类不继承Thread,也可以实现Runnable接口。并将多线程要运行的代码存放在Runnable的run方法中。这样多线程也可以帮助该类运行。这样的操作有一个好处:避免了单继承的局限性。
步骤:
1,定义了实现Runnable接口。
2,覆盖接口的run方法。将多线程要运行的代码存入其中。
3,创建Thread类的对象(创建线程),并将Runnable接口的子类对象作为参数传递给Thread的构造函数。因为线程要运行的代码都在Runnable子类的run方法中存储。所以要将该run方法所属的对象传递给Thread。让Thread线程去使用该对象调用其run方法。
4,调用Thread对象的start方法。开启线程。
实现方式好处:避免了单继承的局限性。
实现方式和继承方式区别?
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。
示例:多个窗口同时买票2,实现Runnable接口。
classTicketimplements
Runnable{
privateinttick=100;
//覆盖run方法
publicvoidrun(){
while(true){
if(tick>0){
System.out.println(Thread.currentThread().getName()+"....sale:"+tick——);
}
}
}
}
classTicketDemo{
publicstaticvoidmain(String[]args){
Tickett=newTicket();
Threadt1=newThread(t);//创建了一个线程;
Threadt2=newThread(t);//创建了一个线程;
Threadt3=newThread(t);//创建了一个线程;
Threadt4=newThread(t);//创建了一个线程;
t1.start();
t2.start();
t3.start();
t4.start();
}
}
第二重点:同步的所有特性
线程的状态。
1,被创建。
2,运行。
3,冻结。
冻结状态的特点:放弃了执行资格。
①,sleep(time)当sleep时间到就又开始运行
②,wait()当调用notify()时线程开始运行
4,消亡。
5,还有一种特殊的状态:临时状态。
该临时状态的特点:
具备了执行资格,但不具备执行权,多线程具备随机性。因为是由cpu不断的快速切换造成的。就有可能会产生多线程的安全问题。
问题的产生的原因:
几个关键点:
1,多线程代码中有操作共享数据。
2,多条语句操作该共享数据。
当具备两个关键点时,有一个线程对多条操作共享数据的代码执行的一部分。还没有执行完,另一个线程开始参与执行。就会发生数据错误。
解决方法:
当一个线程在执行多条操作共享数据代码时,其他线程即使获取了执行权,也不可以参与操作。
Java对于多线程的安全问题提供了专业的解决方式。就是同步代码块。
同步的原理:就是将部分操作功能数据的代码进行加锁。
同步的表现形式:
1,同步代码块。
synchronized(对象)
{
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。
2,同步函数。
两者的不同:
同步代码块使用的锁是任意对象。
同步函数使用的锁是this。
注意:对于static的同步函数,使用的锁不是this。是类名.Class是该类的字节码文件对象。
涉及到了单例设计模式的懒汉式。
单例设计模式的懒汉式
classSingle{
privatestaticSingles=null;
privateSingle(){}
publicstaticSinglegetInstance(){
if(s==null){
synchronized(Single.class){
if(s==null)
s=newSingle();
}
}
returns;
}
}
同步的好处:解决了线程的安全问题。
弊端:
较为消耗资源。同步嵌套后,容易死锁。
要记住:同步使用的前提:
1,必须是两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
这是才可以称为这些线程被同步了。
停止线程:
原理:run方法结束。run方法中通常定义循环,指定控制住循环线程即可结束。
1,定义结束标记。
2,当线程处于了冻结状态,没有执行标记,程序一样无法结束。这时可以循环,正常退出冻结状态,或者强制结束冻结状态。
强制结束冻结状态:interrupt();目的是线程强制从冻结状态恢复到运行状态。但是会发生InterruptedException异常。
线程中一些常见方法:
setDaemon(boolean):将线程标记为后台线程,后台线程和前台线程一样,开启,一样抢执行权运行,只有在结束时,有区别,当前台线程都运行结束后,后台线程会自动结束。
join():等待该线程结束。当A线程执行到了B的.join方法时,A就会处于冻结状态。A什么时候运行?当B运行结束后,A就会具备运行资格,继续运行。加入线程,可以完成对某个线程的临时加入执行。
线程间通信。
等待/唤醒机制。
也就是常见的生产者消费者问题。
1.当多个生产者消费者出现时,需要让获取执行权的线程判断标记。通过while完成。
2.需要将对方的线程唤醒。仅仅用notify,是不可以的。因为有可能出现只唤醒本方。有可能会导致,所有线程都等待。所以可以通过notifyAll的形式来完成。
wait():释放cpu执行权,释放锁。
sleep():释放cpu执行权,不释放锁
JDK1.5版本提供了一些新的对象,优化了等待唤醒机制。
1,将synchronized替换成了Lock接口。将隐式锁,升级成了显示锁。
获取锁:lock();
释放锁:unlock();注意:释放的动作一定要执行,所以通常定义在finally中。
获取Condition对象:newCondition();
2,将Object中的wait,notify,notifyAll方法都替换成了Condition的await,signal,signalAll。和以前不同是:一个同步代码块具备一个锁,该所以具备自己的独立wait和notify方法。现在是将wait,notify等方法,封装进一个特有的对象Condition,而一个Lock锁上可以有多个Condition对象。
死锁。同步中嵌套同步。
classTicketimplementsRunnable{
privateinttick=1000;
Objectobj=newObject();
booleanflag=true;
publicvoidrun(){
if(flag){
while(true){
synchronized(obj){
show();
}
}
}
else
while(true)
show();
}
publicsynchronizedvoidshow()//this{
synchronized(obj){
if(tick>0){
try{Thread.sleep(10);}catch(Exceptione){}
System.out.println(Thread.currentThread().getName()+"....code:"+tick——);
}
}
}
}
classDeadLock{
publicstaticvoidmain(String[]args){
Tickett=newTicket();
Threadt1=newThread(t);
Threadt2=newThread(t);
t1.start();
try{Thread.sleep(10);}catch(Exceptione){}
t.flag=false;
t2.start();
}
}
线程类的其他方法
setPriority(intnum)
setDaemon(booleanb)
join()
toString()
多线程。第一重点:创建线程的两种方式。第二重点:同步的所有特性
进程:正在执行的程序。
线程:是进程中用于控制程序执行的控制单元(执行路径,执行情景)进程中至少有一个线程。
对于JVM,启动时,有两个线程:jvm的主线程。jvm的垃圾回收线程。
第一重点:创建线程的两种方式
如何在程序中自定义线程?
Java给我们提供了对象线程这类事物的描述。该类是Thread
该类中定义了,
创建线程对象的方法(构造函数).
提供了要被线程执行的代码存储的位置run()
开启线程运行的方法start()
还有一些其他的方法用于操作线程:
staticThreadcurrentThead()//获取当前线程对象。
getName()://返回该线程的名称。
staticvoidsleep(time)throwsInterruptedException:
join()方法//等待该线程终止。
创建线程的第一种方式是:继承Thread类。
原因:要覆盖run方法,定义线程要运行的代码。
步骤:
1,继承Thread类。
2,覆盖run方法。将线程要运行的代码定义其中。
3,创建Thread类的子类对象,其实就是在创建线程,调用start方法。
示例:多个窗口同时买票1,继承Thread类
classTicketextends
Thread{
//
static让四个卖票窗口共享100票
privatestaticinttick=100;
//覆盖run方法
publicvoidrun(){
while(true){
if(tick>0){
System.out.println(Thread.currentThread().getName()+"....sale:"+tick——);
}
}
}
}
classTicketDemo{
publicstaticvoidmain(String[]args){
Tickett1=newTicket();
Tickett2=newTicket();
Tickett3=newTicket();
Tickett4=newTicket();
//调用start方法
t1.start();
t2.start();
t3.start();
t4.start();
}
}
创建线程的第二种方式:实现Runnable接口。
如果自定义类中有多线程要运行的代码。但是该类有自己的父类。那么就不可以在继承Thread。Java给我们提供了一个规则。Runnable接口。
如果自定义类不继承Thread,也可以实现Runnable接口。并将多线程要运行的代码存放在Runnable的run方法中。这样多线程也可以帮助该类运行。这样的操作有一个好处:避免了单继承的局限性。
步骤:
1,定义了实现Runnable接口。
2,覆盖接口的run方法。将多线程要运行的代码存入其中。
3,创建Thread类的对象(创建线程),并将Runnable接口的子类对象作为参数传递给Thread的构造函数。因为线程要运行的代码都在Runnable子类的run方法中存储。所以要将该run方法所属的对象传递给Thread。让Thread线程去使用该对象调用其run方法。
4,调用Thread对象的start方法。开启线程。
实现方式好处:避免了单继承的局限性。
实现方式和继承方式区别?
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。
示例:多个窗口同时买票2,实现Runnable接口。
classTicketimplements
Runnable{
privateinttick=100;
//覆盖run方法
publicvoidrun(){
while(true){
if(tick>0){
System.out.println(Thread.currentThread().getName()+"....sale:"+tick——);
}
}
}
}
classTicketDemo{
publicstaticvoidmain(String[]args){
Tickett=newTicket();
Threadt1=newThread(t);//创建了一个线程;
Threadt2=newThread(t);//创建了一个线程;
Threadt3=newThread(t);//创建了一个线程;
Threadt4=newThread(t);//创建了一个线程;
t1.start();
t2.start();
t3.start();
t4.start();
}
}
第二重点:同步的所有特性
线程的状态。
1,被创建。
2,运行。
3,冻结。
冻结状态的特点:放弃了执行资格。
①,sleep(time)当sleep时间到就又开始运行
②,wait()当调用notify()时线程开始运行
4,消亡。
5,还有一种特殊的状态:临时状态。
该临时状态的特点:
具备了执行资格,但不具备执行权,多线程具备随机性。因为是由cpu不断的快速切换造成的。就有可能会产生多线程的安全问题。
问题的产生的原因:
几个关键点:
1,多线程代码中有操作共享数据。
2,多条语句操作该共享数据。
当具备两个关键点时,有一个线程对多条操作共享数据的代码执行的一部分。还没有执行完,另一个线程开始参与执行。就会发生数据错误。
解决方法:
当一个线程在执行多条操作共享数据代码时,其他线程即使获取了执行权,也不可以参与操作。
Java对于多线程的安全问题提供了专业的解决方式。就是同步代码块。
同步的原理:就是将部分操作功能数据的代码进行加锁。
同步的表现形式:
1,同步代码块。
synchronized(对象)
{
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。
2,同步函数。
两者的不同:
同步代码块使用的锁是任意对象。
同步函数使用的锁是this。
注意:对于static的同步函数,使用的锁不是this。是类名.Class是该类的字节码文件对象。
涉及到了单例设计模式的懒汉式。
单例设计模式的懒汉式
classSingle{
privatestaticSingles=null;
privateSingle(){}
publicstaticSinglegetInstance(){
if(s==null){
synchronized(Single.class){
if(s==null)
s=newSingle();
}
}
returns;
}
}
同步的好处:解决了线程的安全问题。
弊端:
较为消耗资源。同步嵌套后,容易死锁。
要记住:同步使用的前提:
1,必须是两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
这是才可以称为这些线程被同步了。
停止线程:
原理:run方法结束。run方法中通常定义循环,指定控制住循环线程即可结束。
1,定义结束标记。
2,当线程处于了冻结状态,没有执行标记,程序一样无法结束。这时可以循环,正常退出冻结状态,或者强制结束冻结状态。
强制结束冻结状态:interrupt();目的是线程强制从冻结状态恢复到运行状态。但是会发生InterruptedException异常。
线程中一些常见方法:
setDaemon(boolean):将线程标记为后台线程,后台线程和前台线程一样,开启,一样抢执行权运行,只有在结束时,有区别,当前台线程都运行结束后,后台线程会自动结束。
join():等待该线程结束。当A线程执行到了B的.join方法时,A就会处于冻结状态。A什么时候运行?当B运行结束后,A就会具备运行资格,继续运行。加入线程,可以完成对某个线程的临时加入执行。
线程间通信。
等待/唤醒机制。
也就是常见的生产者消费者问题。
1.当多个生产者消费者出现时,需要让获取执行权的线程判断标记。通过while完成。
2.需要将对方的线程唤醒。仅仅用notify,是不可以的。因为有可能出现只唤醒本方。有可能会导致,所有线程都等待。所以可以通过notifyAll的形式来完成。
wait():释放cpu执行权,释放锁。
sleep():释放cpu执行权,不释放锁
JDK1.5版本提供了一些新的对象,优化了等待唤醒机制。
1,将synchronized替换成了Lock接口。将隐式锁,升级成了显示锁。
获取锁:lock();
释放锁:unlock();注意:释放的动作一定要执行,所以通常定义在finally中。
获取Condition对象:newCondition();
2,将Object中的wait,notify,notifyAll方法都替换成了Condition的await,signal,signalAll。和以前不同是:一个同步代码块具备一个锁,该所以具备自己的独立wait和notify方法。现在是将wait,notify等方法,封装进一个特有的对象Condition,而一个Lock锁上可以有多个Condition对象。
死锁。同步中嵌套同步。
classTicketimplementsRunnable{
privateinttick=1000;
Objectobj=newObject();
booleanflag=true;
publicvoidrun(){
if(flag){
while(true){
synchronized(obj){
show();
}
}
}
else
while(true)
show();
}
publicsynchronizedvoidshow()//this{
synchronized(obj){
if(tick>0){
try{Thread.sleep(10);}catch(Exceptione){}
System.out.println(Thread.currentThread().getName()+"....code:"+tick——);
}
}
}
}
classDeadLock{
publicstaticvoidmain(String[]args){
Tickett=newTicket();
Threadt1=newThread(t);
Threadt2=newThread(t);
t1.start();
try{Thread.sleep(10);}catch(Exceptione){}
t.flag=false;
t2.start();
}
}
线程类的其他方法
setPriority(intnum)
setDaemon(booleanb)
join()
toString()
出处:http://www.cnblogs.com/In-order-to-tomorrow/p/3528527.html
进程:正在执行的程序。
线程:是进程中用于控制程序执行的控制单元(执行路径,执行情景)进程中至少有一个线程。
对于JVM,启动时,有两个线程:jvm的主线程。jvm的垃圾回收线程。
第一重点:创建线程的两种方式
如何在程序中自定义线程?
Java给我们提供了对象线程这类事物的描述。该类是Thread
该类中定义了,
创建线程对象的方法(构造函数).
提供了要被线程执行的代码存储的位置run()
开启线程运行的方法start()
还有一些其他的方法用于操作线程:
staticThreadcurrentThead()//获取当前线程对象。
getName()://返回该线程的名称。
staticvoidsleep(time)throwsInterruptedException:
join()方法//等待该线程终止。
创建线程的第一种方式是:继承Thread类。
原因:要覆盖run方法,定义线程要运行的代码。
步骤:
1,继承Thread类。
2,覆盖run方法。将线程要运行的代码定义其中。
3,创建Thread类的子类对象,其实就是在创建线程,调用start方法。
示例:多个窗口同时买票1,继承Thread类
classTicketextends
Thread{
//
static让四个卖票窗口共享100票
privatestaticinttick=100;
//覆盖run方法
publicvoidrun(){
while(true){
if(tick>0){
System.out.println(Thread.currentThread().getName()+"....sale:"+tick——);
}
}
}
}
classTicketDemo{
publicstaticvoidmain(String[]args){
Tickett1=newTicket();
Tickett2=newTicket();
Tickett3=newTicket();
Tickett4=newTicket();
//调用start方法
t1.start();
t2.start();
t3.start();
t4.start();
}
}
创建线程的第二种方式:实现Runnable接口。
如果自定义类中有多线程要运行的代码。但是该类有自己的父类。那么就不可以在继承Thread。Java给我们提供了一个规则。Runnable接口。
如果自定义类不继承Thread,也可以实现Runnable接口。并将多线程要运行的代码存放在Runnable的run方法中。这样多线程也可以帮助该类运行。这样的操作有一个好处:避免了单继承的局限性。
步骤:
1,定义了实现Runnable接口。
2,覆盖接口的run方法。将多线程要运行的代码存入其中。
3,创建Thread类的对象(创建线程),并将Runnable接口的子类对象作为参数传递给Thread的构造函数。因为线程要运行的代码都在Runnable子类的run方法中存储。所以要将该run方法所属的对象传递给Thread。让Thread线程去使用该对象调用其run方法。
4,调用Thread对象的start方法。开启线程。
实现方式好处:避免了单继承的局限性。
实现方式和继承方式区别?
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。
示例:多个窗口同时买票2,实现Runnable接口。
classTicketimplements
Runnable{
privateinttick=100;
//覆盖run方法
publicvoidrun(){
while(true){
if(tick>0){
System.out.println(Thread.currentThread().getName()+"....sale:"+tick——);
}
}
}
}
classTicketDemo{
publicstaticvoidmain(String[]args){
Tickett=newTicket();
Threadt1=newThread(t);//创建了一个线程;
Threadt2=newThread(t);//创建了一个线程;
Threadt3=newThread(t);//创建了一个线程;
Threadt4=newThread(t);//创建了一个线程;
t1.start();
t2.start();
t3.start();
t4.start();
}
}
第二重点:同步的所有特性
线程的状态。
1,被创建。
2,运行。
3,冻结。
冻结状态的特点:放弃了执行资格。
①,sleep(time)当sleep时间到就又开始运行
②,wait()当调用notify()时线程开始运行
4,消亡。
5,还有一种特殊的状态:临时状态。
该临时状态的特点:
具备了执行资格,但不具备执行权,多线程具备随机性。因为是由cpu不断的快速切换造成的。就有可能会产生多线程的安全问题。
问题的产生的原因:
几个关键点:
1,多线程代码中有操作共享数据。
2,多条语句操作该共享数据。
当具备两个关键点时,有一个线程对多条操作共享数据的代码执行的一部分。还没有执行完,另一个线程开始参与执行。就会发生数据错误。
解决方法:
当一个线程在执行多条操作共享数据代码时,其他线程即使获取了执行权,也不可以参与操作。
Java对于多线程的安全问题提供了专业的解决方式。就是同步代码块。
同步的原理:就是将部分操作功能数据的代码进行加锁。
同步的表现形式:
1,同步代码块。
synchronized(对象)
{
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。
2,同步函数。
两者的不同:
同步代码块使用的锁是任意对象。
同步函数使用的锁是this。
注意:对于static的同步函数,使用的锁不是this。是类名.Class是该类的字节码文件对象。
涉及到了单例设计模式的懒汉式。
单例设计模式的懒汉式
classSingle{
privatestaticSingles=null;
privateSingle(){}
publicstaticSinglegetInstance(){
if(s==null){
synchronized(Single.class){
if(s==null)
s=newSingle();
}
}
returns;
}
}
同步的好处:解决了线程的安全问题。
弊端:
较为消耗资源。同步嵌套后,容易死锁。
要记住:同步使用的前提:
1,必须是两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
这是才可以称为这些线程被同步了。
停止线程:
原理:run方法结束。run方法中通常定义循环,指定控制住循环线程即可结束。
1,定义结束标记。
2,当线程处于了冻结状态,没有执行标记,程序一样无法结束。这时可以循环,正常退出冻结状态,或者强制结束冻结状态。
强制结束冻结状态:interrupt();目的是线程强制从冻结状态恢复到运行状态。但是会发生InterruptedException异常。
线程中一些常见方法:
setDaemon(boolean):将线程标记为后台线程,后台线程和前台线程一样,开启,一样抢执行权运行,只有在结束时,有区别,当前台线程都运行结束后,后台线程会自动结束。
join():等待该线程结束。当A线程执行到了B的.join方法时,A就会处于冻结状态。A什么时候运行?当B运行结束后,A就会具备运行资格,继续运行。加入线程,可以完成对某个线程的临时加入执行。
线程间通信。
等待/唤醒机制。
也就是常见的生产者消费者问题。
1.当多个生产者消费者出现时,需要让获取执行权的线程判断标记。通过while完成。
2.需要将对方的线程唤醒。仅仅用notify,是不可以的。因为有可能出现只唤醒本方。有可能会导致,所有线程都等待。所以可以通过notifyAll的形式来完成。
wait():释放cpu执行权,释放锁。
sleep():释放cpu执行权,不释放锁
JDK1.5版本提供了一些新的对象,优化了等待唤醒机制。
1,将synchronized替换成了Lock接口。将隐式锁,升级成了显示锁。
获取锁:lock();
释放锁:unlock();注意:释放的动作一定要执行,所以通常定义在finally中。
获取Condition对象:newCondition();
2,将Object中的wait,notify,notifyAll方法都替换成了Condition的await,signal,signalAll。和以前不同是:一个同步代码块具备一个锁,该所以具备自己的独立wait和notify方法。现在是将wait,notify等方法,封装进一个特有的对象Condition,而一个Lock锁上可以有多个Condition对象。
死锁。同步中嵌套同步。
classTicketimplementsRunnable{
privateinttick=1000;
Objectobj=newObject();
booleanflag=true;
publicvoidrun(){
if(flag){
while(true){
synchronized(obj){
show();
}
}
}
else
while(true)
show();
}
publicsynchronizedvoidshow()//this{
synchronized(obj){
if(tick>0){
try{Thread.sleep(10);}catch(Exceptione){}
System.out.println(Thread.currentThread().getName()+"....code:"+tick——);
}
}
}
}
classDeadLock{
publicstaticvoidmain(String[]args){
Tickett=newTicket();
Threadt1=newThread(t);
Threadt2=newThread(t);
t1.start();
try{Thread.sleep(10);}catch(Exceptione){}
t.flag=false;
t2.start();
}
}
线程类的其他方法
setPriority(intnum)
setDaemon(booleanb)
join()
toString()
多线程。第一重点:创建线程的两种方式。第二重点:同步的所有特性
进程:正在执行的程序。
线程:是进程中用于控制程序执行的控制单元(执行路径,执行情景)进程中至少有一个线程。
对于JVM,启动时,有两个线程:jvm的主线程。jvm的垃圾回收线程。
第一重点:创建线程的两种方式
如何在程序中自定义线程?
Java给我们提供了对象线程这类事物的描述。该类是Thread
该类中定义了,
创建线程对象的方法(构造函数).
提供了要被线程执行的代码存储的位置run()
开启线程运行的方法start()
还有一些其他的方法用于操作线程:
staticThreadcurrentThead()//获取当前线程对象。
getName()://返回该线程的名称。
staticvoidsleep(time)throwsInterruptedException:
join()方法//等待该线程终止。
创建线程的第一种方式是:继承Thread类。
原因:要覆盖run方法,定义线程要运行的代码。
步骤:
1,继承Thread类。
2,覆盖run方法。将线程要运行的代码定义其中。
3,创建Thread类的子类对象,其实就是在创建线程,调用start方法。
示例:多个窗口同时买票1,继承Thread类
classTicketextends
Thread{
//
static让四个卖票窗口共享100票
privatestaticinttick=100;
//覆盖run方法
publicvoidrun(){
while(true){
if(tick>0){
System.out.println(Thread.currentThread().getName()+"....sale:"+tick——);
}
}
}
}
classTicketDemo{
publicstaticvoidmain(String[]args){
Tickett1=newTicket();
Tickett2=newTicket();
Tickett3=newTicket();
Tickett4=newTicket();
//调用start方法
t1.start();
t2.start();
t3.start();
t4.start();
}
}
创建线程的第二种方式:实现Runnable接口。
如果自定义类中有多线程要运行的代码。但是该类有自己的父类。那么就不可以在继承Thread。Java给我们提供了一个规则。Runnable接口。
如果自定义类不继承Thread,也可以实现Runnable接口。并将多线程要运行的代码存放在Runnable的run方法中。这样多线程也可以帮助该类运行。这样的操作有一个好处:避免了单继承的局限性。
步骤:
1,定义了实现Runnable接口。
2,覆盖接口的run方法。将多线程要运行的代码存入其中。
3,创建Thread类的对象(创建线程),并将Runnable接口的子类对象作为参数传递给Thread的构造函数。因为线程要运行的代码都在Runnable子类的run方法中存储。所以要将该run方法所属的对象传递给Thread。让Thread线程去使用该对象调用其run方法。
4,调用Thread对象的start方法。开启线程。
实现方式好处:避免了单继承的局限性。
实现方式和继承方式区别?
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。
示例:多个窗口同时买票2,实现Runnable接口。
classTicketimplements
Runnable{
privateinttick=100;
//覆盖run方法
publicvoidrun(){
while(true){
if(tick>0){
System.out.println(Thread.currentThread().getName()+"....sale:"+tick——);
}
}
}
}
classTicketDemo{
publicstaticvoidmain(String[]args){
Tickett=newTicket();
Threadt1=newThread(t);//创建了一个线程;
Threadt2=newThread(t);//创建了一个线程;
Threadt3=newThread(t);//创建了一个线程;
Threadt4=newThread(t);//创建了一个线程;
t1.start();
t2.start();
t3.start();
t4.start();
}
}
第二重点:同步的所有特性
线程的状态。
1,被创建。
2,运行。
3,冻结。
冻结状态的特点:放弃了执行资格。
①,sleep(time)当sleep时间到就又开始运行
②,wait()当调用notify()时线程开始运行
4,消亡。
5,还有一种特殊的状态:临时状态。
该临时状态的特点:
具备了执行资格,但不具备执行权,多线程具备随机性。因为是由cpu不断的快速切换造成的。就有可能会产生多线程的安全问题。
问题的产生的原因:
几个关键点:
1,多线程代码中有操作共享数据。
2,多条语句操作该共享数据。
当具备两个关键点时,有一个线程对多条操作共享数据的代码执行的一部分。还没有执行完,另一个线程开始参与执行。就会发生数据错误。
解决方法:
当一个线程在执行多条操作共享数据代码时,其他线程即使获取了执行权,也不可以参与操作。
Java对于多线程的安全问题提供了专业的解决方式。就是同步代码块。
同步的原理:就是将部分操作功能数据的代码进行加锁。
同步的表现形式:
1,同步代码块。
synchronized(对象)
{
需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。
2,同步函数。
两者的不同:
同步代码块使用的锁是任意对象。
同步函数使用的锁是this。
注意:对于static的同步函数,使用的锁不是this。是类名.Class是该类的字节码文件对象。
涉及到了单例设计模式的懒汉式。
单例设计模式的懒汉式
classSingle{
privatestaticSingles=null;
privateSingle(){}
publicstaticSinglegetInstance(){
if(s==null){
synchronized(Single.class){
if(s==null)
s=newSingle();
}
}
returns;
}
}
同步的好处:解决了线程的安全问题。
弊端:
较为消耗资源。同步嵌套后,容易死锁。
要记住:同步使用的前提:
1,必须是两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
这是才可以称为这些线程被同步了。
停止线程:
原理:run方法结束。run方法中通常定义循环,指定控制住循环线程即可结束。
1,定义结束标记。
2,当线程处于了冻结状态,没有执行标记,程序一样无法结束。这时可以循环,正常退出冻结状态,或者强制结束冻结状态。
强制结束冻结状态:interrupt();目的是线程强制从冻结状态恢复到运行状态。但是会发生InterruptedException异常。
线程中一些常见方法:
setDaemon(boolean):将线程标记为后台线程,后台线程和前台线程一样,开启,一样抢执行权运行,只有在结束时,有区别,当前台线程都运行结束后,后台线程会自动结束。
join():等待该线程结束。当A线程执行到了B的.join方法时,A就会处于冻结状态。A什么时候运行?当B运行结束后,A就会具备运行资格,继续运行。加入线程,可以完成对某个线程的临时加入执行。
线程间通信。
等待/唤醒机制。
也就是常见的生产者消费者问题。
1.当多个生产者消费者出现时,需要让获取执行权的线程判断标记。通过while完成。
2.需要将对方的线程唤醒。仅仅用notify,是不可以的。因为有可能出现只唤醒本方。有可能会导致,所有线程都等待。所以可以通过notifyAll的形式来完成。
wait():释放cpu执行权,释放锁。
sleep():释放cpu执行权,不释放锁
JDK1.5版本提供了一些新的对象,优化了等待唤醒机制。
1,将synchronized替换成了Lock接口。将隐式锁,升级成了显示锁。
获取锁:lock();
释放锁:unlock();注意:释放的动作一定要执行,所以通常定义在finally中。
获取Condition对象:newCondition();
2,将Object中的wait,notify,notifyAll方法都替换成了Condition的await,signal,signalAll。和以前不同是:一个同步代码块具备一个锁,该所以具备自己的独立wait和notify方法。现在是将wait,notify等方法,封装进一个特有的对象Condition,而一个Lock锁上可以有多个Condition对象。
死锁。同步中嵌套同步。
classTicketimplementsRunnable{
privateinttick=1000;
Objectobj=newObject();
booleanflag=true;
publicvoidrun(){
if(flag){
while(true){
synchronized(obj){
show();
}
}
}
else
while(true)
show();
}
publicsynchronizedvoidshow()//this{
synchronized(obj){
if(tick>0){
try{Thread.sleep(10);}catch(Exceptione){}
System.out.println(Thread.currentThread().getName()+"....code:"+tick——);
}
}
}
}
classDeadLock{
publicstaticvoidmain(String[]args){
Tickett=newTicket();
Threadt1=newThread(t);
Threadt2=newThread(t);
t1.start();
try{Thread.sleep(10);}catch(Exceptione){}
t.flag=false;
t2.start();
}
}
线程类的其他方法
setPriority(intnum)
setDaemon(booleanb)
join()
toString()
出处:http://www.cnblogs.com/In-order-to-tomorrow/p/3528527.html
相关文章推荐
- 黑马程序员_java基础笔记(04)...多线程
- 黑马程序员_java基础笔记(04)...多线程
- 黑马程序员——Java语言基础——04.多线程(1)多线程概念
- 黑马程序员-------Java笔记--------多线程基础练习2题
- 黑马程序员——Java语言基础——04.多线程(2)线程间通信
- 黑马程序员---Java基础学习笔记(多线程-后篇)
- 黑马程序员---Java基础学习笔记(多线程-前篇)
- Java基础知识强化之多线程笔记04:并行和并发 区别
- 黑马程序员---------笔记整理(java基础八-----多线程)
- 黑马程序员—10—java基础:有关多线程安全的学习笔记和学习心得体会
- 黑马程序员_java基础学习笔记10_多线程
- 黑马程序员--Java基础学习笔记【序列化、多线程】
- 黑马程序员_java基础学习笔记04_面向对象
- 黑马程序员—Java基础学习笔记之多线程
- 黑马程序员自学笔记 Java基础<五>---> 多线程
- 黑马程序员_java基础_多线程学习笔记
- 黑马程序员_java基础加强9_多线程加强
- 黑马程序员---Java基础--12天(多线程)
- 黑马程序员---------笔记整理(java基础六-----异常)
- 黑马程序员-Java语言基础– 多线程 第12天