黑马程序员---java学习笔记之多线程
2013-12-19 12:07
543 查看
------- android培训、java培训、期待与您交流! ----------
1、什么是进程?进程就是系统正在执行中的程序。每一个进程都有一个执行顺序,该顺序是一个执行路径或者说控制单元。
什么是线程?就是进程中的一个独立单元,线程控制着进程的执行。
一个进程至少有一个线程。
2、jvm启动的时候,有一个java进程,该进程中至少有一个线程负责java程序的执行,该线程称为主线程。
3、jvm虚拟机启动的时候其实是一个多线程。
4、自定义线程方法一:定义一个继承Thread的子类,重写Thread类中的run方法,然后创建对象,调用Thread的start方法。
Thread类中的start方法有两个作用:开启一个线程;调用Thread子类中重写的run方法。
5、主线程执行的是main方法中的代码,自定义线程执行的是子类中重写的run方法中的代码。所以你可以把你想在另一个线程中执行的代码写进子类的run方法里。
6、如果你创建了Thread子类对象,但并没有调用start方法,而是直接调用run方法,这样导致的结果是自定义的线程未被开启,只有主线程在调用run方法。
7、线程的状态:
被创建:线程被创建;
运行状态:当调用Thread类中的start方法,开启线程,线程进入运行状态。在这个状态下,线程具有运行资格且有执行权。
阻塞状态:具备运行资格,但是没有执行权;
冻结状态:线程在遇到sleep(time)时,进入睡眠状态,在定时时间到,自动进入阻塞或者运行状态;线程在遇到wai时进入冻结状态,知道由notify唤醒才能够回到阻塞或运行状态。在冻结状态下,线程放弃了运行资格和执行权;
消亡状态:线程遇到stop方法时,进入消亡状态;或者线程代码执行结束,自动进入消亡状态。消亡状态就是线程的结束。
8、一个java进程里可能有许多的线程,在有线程未被执行结束时,该java进程和jvm是不会关闭的。
9、Thread 类有一个静态的currentThread()方法,用于返回当前线程;Thread类中有一个getName()方法和setName()方法,用于获取当前线程的名字或者设置当前线程的名字。
10、已经start过的线程对象不需要再次对它进行start开启。
11、java中真正创建线程对象的是new Thread(或new 其子类)。
12、创建线程的第2种方法:定义类实现Runnable接口并且重写其run方法然后将该类的对象传递给Thread类的构造方法Thread(Runnable r),然后利用该构造方法创建Thread对象。为什么要将Runnable的实现类对象传递给Thread类的构造函数呢?这是为了由Thread创建的线程对象执行Runnable实现类中的run()方法。
13、创建线程对象的两种方式的区别:
a):继承Thread类去创建线程的类因为java的单继承就不能继承其他的类了,这在该类还需继承其他类的情况下就不太合适了;实现Runnable接口然后传递给Thread相关构造方法的类就可以再继承其他的类;
b):采用继承的方式,其线程运行代码存储在Thread继承子类中;采用实现的方式,其线程运行代码,存储在实现Runnable接口的子类中,存储位置不同。
14、当多个线程执行同一段代码且该代码中设计到共享数据时,有可能会出现共享数据的错误。这时候的一个解决办法就是使用synchronized代码块。
15、使用同步的前提是:
有两个或两个以上的线程;必须是多个线程使用同一个锁(对象)。
16、同步的好处是:解决了多线程的安全问题;弊端是:除带有锁的线程外的其他线程都需要判断锁,耗费了资源,效率可能低一些。
17、同步的表现形式有两种:同步函数和同步代码块。
18、怎么找多线程中的安全问题?
a):首先是找多线程中共同执行的代码;
b):然后是找多线程都会使用到的数据也就是共享数据;
c):最后是明确多线程中哪些数据是操作共享数据的。
19、非静态同步函数的锁是调用该函数的对象this。下面是示例:
20、静态同步函数的锁是该静态函数所在的字节码文件对象。类型是Class,对象名称是类名.class
21、单例设计模式
a):(复习)单例设计模式有两种,一种是饿汉式,一种是懒汉式。
饿汉式:
使用同步函数的方式:
这种方式比较低效,为什么?因为每个要调用该getInstance方法的线程都要进行是否含有锁的判断,比较地耗费资源。
使用同步代码块的形式:
这种方式只要有线程创建了对象,以后进入的线程就只需要判断外层的if(s == null),而不用再去判断是否含有锁了。
22、死锁现象的原因是:同步中嵌套同步,两个同步的锁不一样。
1、什么是进程?进程就是系统正在执行中的程序。每一个进程都有一个执行顺序,该顺序是一个执行路径或者说控制单元。
什么是线程?就是进程中的一个独立单元,线程控制着进程的执行。
一个进程至少有一个线程。
2、jvm启动的时候,有一个java进程,该进程中至少有一个线程负责java程序的执行,该线程称为主线程。
3、jvm虚拟机启动的时候其实是一个多线程。
4、自定义线程方法一:定义一个继承Thread的子类,重写Thread类中的run方法,然后创建对象,调用Thread的start方法。
Thread类中的start方法有两个作用:开启一个线程;调用Thread子类中重写的run方法。
class ThreadTest extends Thread { //创建Thread的子类,并重写其run方法 public void run() { for( int i = 0; i < 60; i++ ) System.out.println("ThreadTest "+i); } } public class ThreadDemo { public static void main(String[] args) { // TODO Auto-generated method stub //创建子类对象 ThreadTest tt = new ThreadTest(); //调用其run方法 tt.start(); for( int i = 0; i < 60; i++ ) System.out.println("ThreadDemo "+i); } }上述代码为创建自定义线程的示例,多次运行打印输出的结果不同可体现出多线程执行时的随机性,亦即cpu在某一时刻只能执行一个线程,之所以会有多个线程同时执行的感觉,因为cpu执行速度非常地快,它在线程之间做着快速的切换。
5、主线程执行的是main方法中的代码,自定义线程执行的是子类中重写的run方法中的代码。所以你可以把你想在另一个线程中执行的代码写进子类的run方法里。
6、如果你创建了Thread子类对象,但并没有调用start方法,而是直接调用run方法,这样导致的结果是自定义的线程未被开启,只有主线程在调用run方法。
7、线程的状态:
被创建:线程被创建;
运行状态:当调用Thread类中的start方法,开启线程,线程进入运行状态。在这个状态下,线程具有运行资格且有执行权。
阻塞状态:具备运行资格,但是没有执行权;
冻结状态:线程在遇到sleep(time)时,进入睡眠状态,在定时时间到,自动进入阻塞或者运行状态;线程在遇到wai时进入冻结状态,知道由notify唤醒才能够回到阻塞或运行状态。在冻结状态下,线程放弃了运行资格和执行权;
消亡状态:线程遇到stop方法时,进入消亡状态;或者线程代码执行结束,自动进入消亡状态。消亡状态就是线程的结束。
8、一个java进程里可能有许多的线程,在有线程未被执行结束时,该java进程和jvm是不会关闭的。
9、Thread 类有一个静态的currentThread()方法,用于返回当前线程;Thread类中有一个getName()方法和setName()方法,用于获取当前线程的名字或者设置当前线程的名字。
10、已经start过的线程对象不需要再次对它进行start开启。
11、java中真正创建线程对象的是new Thread(或new 其子类)。
12、创建线程的第2种方法:定义类实现Runnable接口并且重写其run方法然后将该类的对象传递给Thread类的构造方法Thread(Runnable r),然后利用该构造方法创建Thread对象。为什么要将Runnable的实现类对象传递给Thread类的构造函数呢?这是为了由Thread创建的线程对象执行Runnable实现类中的run()方法。
class Ticket implements Runnable {//实现Runnable接口,并重写run方法 private int ticket = 400; public void run() { while(true) { if( ticket > 0 ) System.out.println(ticket--); else break; } } } public class ThreadDemo2 { public static void main(String[] args) { // TODO Auto-generated method stub //创建Runnable实现类的对象 Ticket t = new Ticket() //创建线程对象的同时将Runnable实现类的对象传递进去 ; Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); } }这是视频中售票的例子。
13、创建线程对象的两种方式的区别:
a):继承Thread类去创建线程的类因为java的单继承就不能继承其他的类了,这在该类还需继承其他类的情况下就不太合适了;实现Runnable接口然后传递给Thread相关构造方法的类就可以再继承其他的类;
b):采用继承的方式,其线程运行代码存储在Thread继承子类中;采用实现的方式,其线程运行代码,存储在实现Runnable接口的子类中,存储位置不同。
14、当多个线程执行同一段代码且该代码中设计到共享数据时,有可能会出现共享数据的错误。这时候的一个解决办法就是使用synchronized代码块。
15、使用同步的前提是:
有两个或两个以上的线程;必须是多个线程使用同一个锁(对象)。
16、同步的好处是:解决了多线程的安全问题;弊端是:除带有锁的线程外的其他线程都需要判断锁,耗费了资源,效率可能低一些。
17、同步的表现形式有两种:同步函数和同步代码块。
18、怎么找多线程中的安全问题?
a):首先是找多线程中共同执行的代码;
b):然后是找多线程都会使用到的数据也就是共享数据;
c):最后是明确多线程中哪些数据是操作共享数据的。
19、非静态同步函数的锁是调用该函数的对象this。下面是示例:
class Ticket1 implements Runnable { private int tick = 100; Object obj = new Object(); boolean flag = true; public void run() { if(flag) { while(true) { synchronized(obj) { try{Thread.sleep(10);}catch(Exception e){} if( tick > 0 ) System.out.println(Thread.currentThread().getName()+" "+tick--); } } } else while(true) { show(); } } synchronized void show() { try{Thread.sleep(10);}catch(Exception e){} if( tick > 0 ) System.out.println(Thread.currentThread().getName()+" "+tick--); } } public class ThreadDemo3 { public static void main(String[] args) { // TODO Auto-generated method stub Ticket1 t = new Ticket1(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try{Thread.sleep(10);}catch(Exception e){} t.flag = false; t2.start(); } }上述代码可能会出现0号票的错票,原因是两个线程同步时使用的并不是同一个锁,要避免错误地话,可将同步代码块的锁改为this.
20、静态同步函数的锁是该静态函数所在的字节码文件对象。类型是Class,对象名称是类名.class
21、单例设计模式
a):(复习)单例设计模式有两种,一种是饿汉式,一种是懒汉式。
饿汉式:
private static final Single s = new Single(); private Single(){} public static Single getInstance() { return s; }懒汉式:
private static Single s = null; private Single(){} public static Single getInstance() { if(s == null) s = new Single(); return s; }分析可知,当多线程执行到懒汉式的getInstace方法时,容易出现安全问题,导致创建了多个Single对象。所以需要对该方法进行同步。
使用同步函数的方式:
public static synchronized Single getInstance() { if(s == null) s = new Single(); return s; }
这种方式比较低效,为什么?因为每个要调用该getInstance方法的线程都要进行是否含有锁的判断,比较地耗费资源。
使用同步代码块的形式:
public static Single getInstance() { if(s == null) { synchronized(Single.class) { if(s == null) s = new Single(); return s; } } }
这种方式只要有线程创建了对象,以后进入的线程就只需要判断外层的if(s == null),而不用再去判断是否含有锁了。
22、死锁现象的原因是:同步中嵌套同步,两个同步的锁不一样。
相关文章推荐
- 黑马程序员---java学习笔记之多线程2
- 黑马程序员之JAVA学习笔记:多线程学习大总结
- 黑马程序员 java学习笔记——多线程2
- 黑马程序员—10—java基础:有关多线程安全的学习笔记和学习心得体会
- 黑马程序员---Java基础学习笔记(多线程-前篇)
- 黑马程序员--Java基础学习笔记【序列化、多线程】
- 黑马程序员_java基础_多线程学习笔记
- 黑马程序员_java多线程学习笔记
- 黑马程序员 JAVA学习笔记 ——— 多线程
- 黑马程序员_java基础学习笔记10_多线程
- 黑马程序员java学习笔记,多线程
- 黑马程序员 java学习笔记——多线程1
- 黑马程序员-Java学习笔记之多线程
- 黑马程序员java学习笔记之四(java多线程总结)
- 黑马程序员学习笔记 Java中多线程与并发的总结
- 黑马程序员---java多线程 学习笔记
- 黑马程序员—Java基础学习笔记之多线程
- 黑马程序员——Java学习笔记之③——“多线程”
- 黑马程序员--Java学习笔记之多线程(自定义线程的两种方式对比、线程状态、线程安全)
- 黑马程序员——Java学习笔记--多线程