黑马程序员-java基础-多线程1

---恢复内容开始---

单线程的程序只有一个顺序流;而多线程的程序则可以包括多个顺序执行流,并且多个顺序流之间互不干扰。就像单线程程序如同只雇佣了一个服务员的餐厅,他只有做完一件事情后才可以做下面一件事情;而多线程程序则是雇佣了多名服务员的餐厅,他们可以同时进行着多件事情。

  JAVA多线程编程的相关知识:创建、启动线程、控制线程、以及多线程的同步操作。

1.概述:

 进程是指正在运行中的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或叫一个执行单元。

 线程是指进程中能够独立执行的控制单元。线程控制着进程的执行。一个进程可以同时运行多个不同的线程。

 两者的区别:

  一个程序运行后至少有一个进程,一个进程里可以包含一个或多个线程。

  每个进程都需要操作系统为其分配独立的内存地址空间,而同一进程中的所有线程在同一块地址空间中工作。这些线程可以共享进程的状态和资源。

2.创建和启动线程:

 创建线程有两种方式:

 1、继承 java.lang.Thread 类。

 2、实现Runnable 接口。

 

2.1 继承Thread 类创建线程类:

  步骤如下 :

1、定义Thread 类的子类,并重写该线程的run() 方法。

  2、创建Thread 类的子类的实例,即创建线程对象。

  3、调用线程的start方法来启动该线程。

 1 //定义Thread 类的子类
 2 class ThreadText extends Thread {
 3 //    重写run()方法
 4     public void run()
 5     {
 6         for (int a = 0 ; a <10 ; a ++)
 7         {
 8             System.out.println( currentThread().getName() + ":" + a);
 9         }
10     }
11 }
12 public class StratThread {
13
14     public static void main(String args[])
15     {
16 //        创建Thread 类的子类的实例
17         ThreadText t = new ThreadText() ;
18 //        调用线程的start()方法来启动该线程
19         t.start() ;
20
21 //         主线程调用用户线程的对象run()方法。
22         t.run() ;
23     }
24 }

  为什么要重写Thread 类的run() 方法?

  Thread 类定义了一个功能,就是用于存储线程要运行的代码,该存储功能就是 run() 方法。即 该run() 方法的方法体就是代表了线程需要完成的任务。所以,我们也把run() 方法称为线程执行体。

 为什么要调用 start() 方法来启动线程,而不是run() 方法?

 因为调用start() 方法来启动线程,系统会把run() 方法当成线程执行体来处理,而如果直接调用线程对象的run() 方法,则系统会把线程对象当成一个普通的对象,而run() 方法也是一个普通方法,而不是线程执行体。

 在上面的代码中第19行和第22行分别调用了start() 和 run() 方法。通过运行的结果如下:

main:0
Thread-0:0
main:1
Thread-0:1
main:2
Thread-0:2
main:3
Thread-0:3
main:4
Thread-0:4
main:5
Thread-0:5
main:6
Thread-0:6
main:7
Thread-0:7
Thread-0:8
Thread-0:9
main:8
main:9

  通过运行结果可以看到两个线程交替运行:t 和 main 线程(当运行JAVA程序时,JVM 首先会创建并启动主线程,主线程从main() 开始运行)。所以,当调用 Thread 类的子类调用start() 方法是启动该线程;而调用run() 方法时则只是让主线程运行其run() 方法中的代码,并没有启动新的线程。

  注意:局部变量在每一个线程中都是独立的一份。

  在上面程序第8行用还用到了Thread 类的两个方法:

  > static Thread currentThread () :  该方法是Thread 类的静态方法,该方法返回当前正在执行的线程对象。

  > String getName() : 该方法是Thread 的实例方法,该方法返回调用该方法的线程的名字。

2.2 实现Runnable 接口创建线程类:

1、定义 Runnable 接口的实现类,并重写该接口的run方法。

  2、创建 Runnable 实现类的实例,并以此实例作为Thread 的target 来创建Thread 对象,该Thread 对象才是真正的线程对象。

  3、调用线程对象的 start() 方法来启动该线程。

  

 1 //定义Runnable 接口的实现类
 2 class RunnableText implements Runnable
 3 {
 4 //    重写接口的run方法。
 5     public void run()
 6     {
 7         for (int a = 0 ; a <10 ; a ++)
 8         {
 9             System.out.println( Thread.currentThread().getName() + ":" + a);
10         }
11     }
12 }
13
14 public class ThreadTextRunnable  {
15
16     public static void main(String args[])
17     {
18 //        创建Runnable 实现类的实例
19         RunnableText t = new RunnableText() ;
20
21 //        通过new Thread(Runnable target ) 创建新线程
22         Thread thread = new Thread(t) ;
23         Thread thread1 = new Thread(t) ;
24
25 //        启动线程。
26         thread.start() ;
27         thread1.start() ;
28     }
29 }

  为什么要将Runnable 实现类的实例传递给Thread 的构造函数?

  因为,自定的run() 方法所属是 Runnable 接口的实现类的实例。所以,要让线程去指定对象的run() 方法,就必须明确该 run() 方法所属的对象。

 

 2.3 两种方式的区别:

    2.3.1 采用实现 Runnable 接口方式的多线程

      1、线程类只是实现了 Runnable 接口。所以,还可以继承其他的类。

      2、在这种方式下,可以多个线程共享同一个target 对象,所以适合多个相同线程处理同一分资源的情况。

    2.3.2 采用继承 Thread 类方式的多线程

      1、因为线程继承了 Thread 类,所以不能继承其他父类。

3.线程的运行状态

  当线程被创建并启动后,并不是已启动就进入执行状态,也不是一直处于执行状态。在线程的生命周期中要经历如下集中状态:新建、就绪、运行、阻塞、和死亡五种状态。

 3.1 新建(New)和就绪(Runnable) 状态:

  当程序使用 new 关键字创建一个线程之后,该线程就处于新建状态,这时候它仅仅由JVM为其分配了内存。

  当线程对象调用 start() 方法之后,该线程就处于就绪状态。这个状态的线程处于有运行资格,却没有运行权利。如何有运行权利则取决于JVM里线程调度器。

  3.2 就绪(Runnable)、运行(Running)和阻塞(Blocked)状态:

  如果就绪状态获得了运行权利,则开始执行 run() 方法 的线程执行体,则该线程处于运行状态。

  当一条线程开始运行时,他不可能一直处于运行状态(除非它的线程执行体足够短,瞬间就执行结束了)。所以当其他的线程抢到CPU的执行权利时,运行状态则重新进入就绪状态。但是当运行状态的线程发生如下情况时,则会进入阻塞状态(放弃所占用的资源,即没有执行资格):

  1、线程调用sleep 方法。当sleep(time)  的时间到了 ,线程又会进入就绪状态。

  2、线程试图获得一个同步监视器,但该同步监视器正在被其他线程所持有。

  3、线程在等待某个通知(notify、notifyAll),即被wait 挂起。

3.3 线程死亡(Dead)

  线程结束后就处于死亡状态:

  1、run() 方法执行完成,线程正常结束。

  2、线程异常。

  3、直接调用该线程的stop() 方法来结束该线程。

  注意:不要对处于死亡状态的线程调用 start() 方法,程序只能对新建状态的线程调用 start() 方法。同时对新建状态的线程两次调用start() 方法也是错误的。

4.控制线程

  4.1 join 线程

  当A 线程执行到了 B 线程的join() 方法时,A 线程就会等待,等 B 线程执行完,A 才会执行。即A 线程 等待B 线程终止。

 

 1 // 定义Runnable 接口的实现类
 2 public class JoinText implements Runnable {
 3 //    重写run() 方法
 4     public void run()
 5     {
 6         for ( int i = 0; i <= 10  ; ++ i)
 7             System.out.println(Thread.currentThread().getName()+ "..." + i);
 8     }
 9     public static void main(String args[]) throws InterruptedException
10     {
11 //        创建Runnable 接口实现类的实例
12         JoinText t = new JoinText()  ;
13 //        通过 Thread(Runnable target) 创建新线程
14         Thread thread = new Thread(t)  ;
15         Thread thread1 = new Thread(t) ;
16 //        启动线程
17         thread.start() ;
18 //        只有等thread 线程执行结束,main 线程才会向下执行;
19         thread.join() ;
20         System.out.println("thread1 线程将要启动");
21         thread1.start() ;
22     }
23 }

  在上面程序中,thread 线程调用了join() 方法。所以main 线程会等 thread 线程执行结束才会向下执行,所以运行的结果如下:

Thread-0...0
Thread-0...1
Thread-0...2
Thread-0...3
Thread-0...4
Thread-0...5
Thread-0...6
Thread-0...7
Thread-0...8
Thread-0...9
Thread-0...10
thread1 线程将要启动
Thread-1...0
Thread-1...1
Thread-1...2
Thread-1...3
Thread-1...4
Thread-1...5
Thread-1...6
Thread-1...7
Thread-1...8
Thread-1...9
Thread-1...10

  join 的方法有三种重载形式:

  void join() : 等待该线程终止。

  void join(long millis) : 等待该线程中指的时间最长为 millis 毫秒。

  void join(long millis , int nanos) 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。

 

4.2 守护线程(后台线程)

  Daemon Thread ,JVM 的垃圾回收机制就是典型的 后台线程。

  调用 Thread 对象 setDaemon(true) 方法可以指定线程设置成后台线程。该方法必须在启动线程钱调用,否则会引发 IllegalThreadStateException 异常。

  后台线程特点:如果所有前台线程都死亡,后台线程会自动死亡。

 1 public class DaemonText implements Runnable {
 2     public void run()
 3     {
 4         for (int i = 0 ; i < 1000 ; i ++)
 5         {
 6             System.out.println(Thread.currentThread().getName()+"..."+i);
 7         }
 8     }
 9     public static void main(String args[])
10     {
11         DaemonText t = new DaemonText()  ;
12         Thread thread = new Thread(t) ;
13
14 //        将次线程设置为后台线程
15         thread.setDaemon(true) ;
16 //        启动后台线程
17         thread.start() ;
18
19         for(int i = 0 ; i < 10; i ++)
20         {
21             System.out.println(Thread.currentThread().getName()+"......"+i);
22         }
23 //        程序执行到此,前台线程结束。
24 //        后台线程也随之结束。
25     }
26 }

  因为thread 线程被设置成了 后台线程。所以,当主线程运行完后 ,JVM 会主动退出,因而后台线程也被结束。

  4.3 线程睡眠:sleep

  当当前线程调用 sleep 方法进入阻塞状态后,在其sleep 时间段内,该线程不会获得执行机会,即使系统中没有其他线程了,直到sleep 的时间到了。所以,调用sleep 能让线程暂短暂停。

  4.4 线程让步:yield

  和sleep 类似,也可以让当前执行的线程暂停,但他不会让线程进入阻塞状态。而是,取消当前线程的执行权,使当前线程进入就绪状态。就是相当于让系统的线程调度器重新调度一次。

  4.5 改变线程的优先级

  每个线程执行时都具有一定的优先级,优先级高的则获得多的运行机会,优先级低的则获得较少的运行机会。

  Thread 提供了 setPriority(int newPriority) 和 getPriority() 方法来设置和返回指定线程的优先级。设置优先级的整数在1~10之间,也可以使用Thread 类的三个静态常量:

  > MAX_PRIORITY : 其值是 10

  > MIN_PRIORITY : 其值是 1

  > NORM_PRIORITY: 其值是 5

---恢复内容结束---

---恢复内容开始---

单线程的程序只有一个顺序流;而多线程的程序则可以包括多个顺序执行流,并且多个顺序流之间互不干扰。就像单线程程序如同只雇佣了一个服务员的餐厅,他只有做完一件事情后才可以做下面一件事情;而多线程程序则是雇佣了多名服务员的餐厅,他们可以同时进行着多件事情。

  JAVA多线程编程的相关知识:创建、启动线程、控制线程、以及多线程的同步操作。

1.概述:

 进程是指正在运行中的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或叫一个执行单元。

 线程是指进程中能够独立执行的控制单元。线程控制着进程的执行。一个进程可以同时运行多个不同的线程。

 两者的区别:

  一个程序运行后至少有一个进程,一个进程里可以包含一个或多个线程。

  每个进程都需要操作系统为其分配独立的内存地址空间,而同一进程中的所有线程在同一块地址空间中工作。这些线程可以共享进程的状态和资源。

2.创建和启动线程:

 创建线程有两种方式:

 1、继承 java.lang.Thread 类。

 2、实现Runnable 接口。

 

2.1 继承Thread 类创建线程类:

  步骤如下 :

1、定义Thread 类的子类,并重写该线程的run() 方法。

  2、创建Thread 类的子类的实例,即创建线程对象。

  3、调用线程的start方法来启动该线程。

 1 //定义Thread 类的子类
 2 class ThreadText extends Thread {
 3 //    重写run()方法
 4     public void run()
 5     {
 6         for (int a = 0 ; a <10 ; a ++)
 7         {
 8             System.out.println( currentThread().getName() + ":" + a);
 9         }
10     }
11 }
12 public class StratThread {
13
14     public static void main(String args[])
15     {
16 //        创建Thread 类的子类的实例
17         ThreadText t = new ThreadText() ;
18 //        调用线程的start()方法来启动该线程
19         t.start() ;
20
21 //         主线程调用用户线程的对象run()方法。
22         t.run() ;
23     }
24 }

  为什么要重写Thread 类的run() 方法?

  Thread 类定义了一个功能,就是用于存储线程要运行的代码,该存储功能就是 run() 方法。即 该run() 方法的方法体就是代表了线程需要完成的任务。所以,我们也把run() 方法称为线程执行体。

 为什么要调用 start() 方法来启动线程,而不是run() 方法?

 因为调用start() 方法来启动线程,系统会把run() 方法当成线程执行体来处理,而如果直接调用线程对象的run() 方法,则系统会把线程对象当成一个普通的对象,而run() 方法也是一个普通方法,而不是线程执行体。

 在上面的代码中第19行和第22行分别调用了start() 和 run() 方法。通过运行的结果如下:

main:0
Thread-0:0
main:1
Thread-0:1
main:2
Thread-0:2
main:3
Thread-0:3
main:4
Thread-0:4
main:5
Thread-0:5
main:6
Thread-0:6
main:7
Thread-0:7
Thread-0:8
Thread-0:9
main:8
main:9

  通过运行结果可以看到两个线程交替运行:t 和 main 线程(当运行JAVA程序时,JVM 首先会创建并启动主线程,主线程从main() 开始运行)。所以,当调用 Thread 类的子类调用start() 方法是启动该线程;而调用run() 方法时则只是让主线程运行其run() 方法中的代码,并没有启动新的线程。

  注意:局部变量在每一个线程中都是独立的一份。

  在上面程序第8行用还用到了Thread 类的两个方法:

  > static Thread currentThread () :  该方法是Thread 类的静态方法,该方法返回当前正在执行的线程对象。

  > String getName() : 该方法是Thread 的实例方法,该方法返回调用该方法的线程的名字。

2.2 实现Runnable 接口创建线程类:

1、定义 Runnable 接口的实现类,并重写该接口的run方法。

  2、创建 Runnable 实现类的实例,并以此实例作为Thread 的target 来创建Thread 对象,该Thread 对象才是真正的线程对象。

  3、调用线程对象的 start() 方法来启动该线程。

  

 1 //定义Runnable 接口的实现类
 2 class RunnableText implements Runnable
 3 {
 4 //    重写接口的run方法。
 5     public void run()
 6     {
 7         for (int a = 0 ; a <10 ; a ++)
 8         {
 9             System.out.println( Thread.currentThread().getName() + ":" + a);
10         }
11     }
12 }
13
14 public class ThreadTextRunnable  {
15
16     public static void main(String args[])
17     {
18 //        创建Runnable 实现类的实例
19         RunnableText t = new RunnableText() ;
20
21 //        通过new Thread(Runnable target ) 创建新线程
22         Thread thread = new Thread(t) ;
23         Thread thread1 = new Thread(t) ;
24
25 //        启动线程。
26         thread.start() ;
27         thread1.start() ;
28     }
29 }

  为什么要将Runnable 实现类的实例传递给Thread 的构造函数?

  因为,自定的run() 方法所属是 Runnable 接口的实现类的实例。所以,要让线程去指定对象的run() 方法,就必须明确该 run() 方法所属的对象。

 

 2.3 两种方式的区别:

    2.3.1 采用实现 Runnable 接口方式的多线程

      1、线程类只是实现了 Runnable 接口。所以,还可以继承其他的类。

      2、在这种方式下,可以多个线程共享同一个target 对象,所以适合多个相同线程处理同一分资源的情况。

    2.3.2 采用继承 Thread 类方式的多线程

      1、因为线程继承了 Thread 类,所以不能继承其他父类。

3.线程的运行状态

  当线程被创建并启动后,并不是已启动就进入执行状态,也不是一直处于执行状态。在线程的生命周期中要经历如下集中状态:新建、就绪、运行、阻塞、和死亡五种状态。

 3.1 新建(New)和就绪(Runnable) 状态:

  当程序使用 new 关键字创建一个线程之后,该线程就处于新建状态,这时候它仅仅由JVM为其分配了内存。

  当线程对象调用 start() 方法之后,该线程就处于就绪状态。这个状态的线程处于有运行资格,却没有运行权利。如何有运行权利则取决于JVM里线程调度器。

  3.2 就绪(Runnable)、运行(Running)和阻塞(Blocked)状态:

  如果就绪状态获得了运行权利,则开始执行 run() 方法 的线程执行体,则该线程处于运行状态。

  当一条线程开始运行时,他不可能一直处于运行状态(除非它的线程执行体足够短,瞬间就执行结束了)。所以当其他的线程抢到CPU的执行权利时,运行状态则重新进入就绪状态。但是当运行状态的线程发生如下情况时,则会进入阻塞状态(放弃所占用的资源,即没有执行资格):

  1、线程调用sleep 方法。当sleep(time)  的时间到了 ,线程又会进入就绪状态。

  2、线程试图获得一个同步监视器,但该同步监视器正在被其他线程所持有。

  3、线程在等待某个通知(notify、notifyAll),即被wait 挂起。

3.3 线程死亡(Dead)

  线程结束后就处于死亡状态:

  1、run() 方法执行完成,线程正常结束。

  2、线程异常。

  3、直接调用该线程的stop() 方法来结束该线程。

  注意:不要对处于死亡状态的线程调用 start() 方法,程序只能对新建状态的线程调用 start() 方法。同时对新建状态的线程两次调用start() 方法也是错误的。

4.控制线程

  4.1 join 线程

  当A 线程执行到了 B 线程的join() 方法时,A 线程就会等待,等 B 线程执行完,A 才会执行。即A 线程 等待B 线程终止。

 

 1 // 定义Runnable 接口的实现类
 2 public class JoinText implements Runnable {
 3 //    重写run() 方法
 4     public void run()
 5     {
 6         for ( int i = 0; i <= 10  ; ++ i)
 7             System.out.println(Thread.currentThread().getName()+ "..." + i);
 8     }
 9     public static void main(String args[]) throws InterruptedException
10     {
11 //        创建Runnable 接口实现类的实例
12         JoinText t = new JoinText()  ;
13 //        通过 Thread(Runnable target) 创建新线程
14         Thread thread = new Thread(t)  ;
15         Thread thread1 = new Thread(t) ;
16 //        启动线程
17         thread.start() ;
18 //        只有等thread 线程执行结束,main 线程才会向下执行;
19         thread.join() ;
20         System.out.println("thread1 线程将要启动");
21         thread1.start() ;
22     }
23 }

  在上面程序中,thread 线程调用了join() 方法。所以main 线程会等 thread 线程执行结束才会向下执行,所以运行的结果如下:

Thread-0...0
Thread-0...1
Thread-0...2
Thread-0...3
Thread-0...4
Thread-0...5
Thread-0...6
Thread-0...7
Thread-0...8
Thread-0...9
Thread-0...10
thread1 线程将要启动
Thread-1...0
Thread-1...1
Thread-1...2
Thread-1...3
Thread-1...4
Thread-1...5
Thread-1...6
Thread-1...7
Thread-1...8
Thread-1...9
Thread-1...10

  join 的方法有三种重载形式:

  void join() : 等待该线程终止。

  void join(long millis) : 等待该线程中指的时间最长为 millis 毫秒。

  void join(long millis , int nanos) 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。

 

4.2 守护线程(后台线程)

  Daemon Thread ,JVM 的垃圾回收机制就是典型的 后台线程。

  调用 Thread 对象 setDaemon(true) 方法可以指定线程设置成后台线程。该方法必须在启动线程钱调用,否则会引发 IllegalThreadStateException 异常。

  后台线程特点:如果所有前台线程都死亡,后台线程会自动死亡。

 1 public class DaemonText implements Runnable {
 2     public void run()
 3     {
 4         for (int i = 0 ; i < 1000 ; i ++)
 5         {
 6             System.out.println(Thread.currentThread().getName()+"..."+i);
 7         }
 8     }
 9     public static void main(String args[])
10     {
11         DaemonText t = new DaemonText()  ;
12         Thread thread = new Thread(t) ;
13
14 //        将次线程设置为后台线程
15         thread.setDaemon(true) ;
16 //        启动后台线程
17         thread.start() ;
18
19         for(int i = 0 ; i < 10; i ++)
20         {
21             System.out.println(Thread.currentThread().getName()+"......"+i);
22         }
23 //        程序执行到此,前台线程结束。
24 //        后台线程也随之结束。
25     }
26 }

  因为thread 线程被设置成了 后台线程。所以,当主线程运行完后 ,JVM 会主动退出,因而后台线程也被结束。

  4.3 线程睡眠:sleep

  当当前线程调用 sleep 方法进入阻塞状态后,在其sleep 时间段内,该线程不会获得执行机会,即使系统中没有其他线程了,直到sleep 的时间到了。所以,调用sleep 能让线程暂短暂停。

  4.4 线程让步:yield

  和sleep 类似,也可以让当前执行的线程暂停,但他不会让线程进入阻塞状态。而是,取消当前线程的执行权,使当前线程进入就绪状态。就是相当于让系统的线程调度器重新调度一次。

  4.5 改变线程的优先级

  每个线程执行时都具有一定的优先级,优先级高的则获得多的运行机会,优先级低的则获得较少的运行机会。

  Thread 提供了 setPriority(int newPriority) 和 getPriority() 方法来设置和返回指定线程的优先级。设置优先级的整数在1~10之间,也可以使用Thread 类的三个静态常量:

  > MAX_PRIORITY : 其值是 10

  > MIN_PRIORITY : 其值是 1

  > NORM_PRIORITY: 其值是 5

---恢复内容结束---

时间: 2024-11-08 21:39:20

黑马程序员-java基础-多线程1的相关文章

黑马程序员——java基础——多线程

 黑马程序员--java基础--多线程 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行.一个进程中至少有一个线程. 一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序,每个线程在栈区中都有自己的执行空间,自己的方法区.自己的变量.

黑马程序员--Java基础--多线程|线程同步

--Java培训.Android培训.iOS培训..Net培训 期待与您共同交流!-- 多线程基础.线程同步 1. 多线程基础 1.1. 进程和线程 1.1.1. 什么是进程 所谓进程(process)就是一块包含了某些资源的内存区域.操作系统利用进程把它的工作划分为一些功能单元.进程中所包含的一个或多个执行单元称为线程(thread).进程还拥有一个私有的虚拟地址空间,该空间仅能被它所包含的线程访问.线程只能归属于一个进程并且它只能访问该进程所拥有的资源.当操作系统创建一个进程后,该进程会自动

黑马程序员-java基础-多线程2

5.多线程的安全问题:多线程同步 当使用多个线程同时访问一个数据时,经常会出现线程安全问题.如下面程序: 1 package Thread; 2 3 /* 4 * 多个线程同时访问一个数据时,出现的安全问题. 5 * 模拟一个卖火车票系统:一共有100张票,多个窗口同时卖票 6 */ 7 class Ticks implements Runnable 8 { 9 private int ticks = 100 ; 10 public void run() 11 { 12 while (ticks

黑马程序员——java基础---多线程

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 学习多线程之前,需对以下几个概念有所认知: 进程:进程是动态的.是一个正在执行中的程序.每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元. 线程:线程依附于进程,可以理解为进程下的一个子执行路径,但没有进程线程无法单独执行. 两者间的区别:进程是重量级的计算机任务,需要给它分配独立的地址空间和系统资源等.不同进程的内部数据和状态都是完全独立,所以不同进程之间的通信或转换

黑马程序员——java基础---多线程(二)

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! -------  线程间的通信:简单来说,就是多个线程在操作同一资源,但操作的动作不同. 试想一下,对于同一个资源做不同的操作,这势必会在操作的过程中产生矛盾.为了避免这种情况的发生,就需要用的synchronized来保证,每次对共享资源的操作,只能是一条线程在进行.在用到同步的时候,就会因需求问题用到wait().notify().notifyAll()这三个方法. wait()方法:作用是使调用线程自动

黑马程序员-Java基础-多线程

第一讲  多线程概述 1. 定义 进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元.在程序运行时,会被分配一个内存空间,进程就用于标识这个空间,封装单元,线程才是线程中真正执行的哦部分. 线程:就是进程中的一个独立的控制单元,线程在控制着进程的执行. 一个进程中至少有一个线程. 例子:java JVM 启动时会有一个进程java.exe.该进程中至少一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中,该线程就称为主线程

黑马程序员——Java基础知识之多线程协同

多线程协同 线程间的通讯:对资源的操作动作不同,比如说两个卡车一个拉煤一个装煤,但是他们共享了一个资源. 怎么样把这个资源拿出来?怎样把车装满?这个资源当然是一个类,他里面的组成元素就是对象!!现在我们就要有操作对象的思想了,用对象把这车装满,现在一车装一个对象. 等待唤醒机制: 用的不是sleep是wait.flag标记,这是两人沟通的方式.其实每个标记就要做一次等待或者notify,判断wait,改值notify.线程池.notify唤醒里面的线程,按顺序唤醒.wait和notify必须用在

黑马程序员——Java基础---IO(下)

黑马程序员——Java基础---IO(下) ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java除了基本的字节流.字符流之外,还提供了File类.properties类.打印流.序列流等和输入输出相关的类,它们能够帮助我们更好的处理信息.下面将对它们进行简单的介绍. 一.正

黑马程序员——Java基础---集合框架工具类

黑马程序员——Java基础<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java为操作Set.List和Map提供了一系列工具类,主要有Collections和Arrays.这两个工具类的特点:类中的方法都是静态的,不需要创建对象,直接使用类名调用即可.Collections:是集合对象