A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Kevin.Kang 高级黑马   /  2015-8-3 15:31  /  1344 人查看  /  24 人回复  /   2 人收藏 转载请遵从CC协议 禁止商业使用本文

多线程:
    如果程序只有一条执行路径,那么该程序就是单线程程序。
    如果程序有多条执行路径,该程序就是多线程程序。

进程:
    正在运行的程序就是进程
    进程是系统进行资源分配和调用的独立单位,每一个进程都有它自己的内存空间和系统资源。

多进程意义:
    单进程的计算机同一时间只能做一件事情,现在的计算机可以做很多事情。
    也就是说现在的计算机支持多进程,可以在同一时间段内执行多个任务。并且提高CPU的使用率。

    一边打游戏,一边听音乐,不是同时进行的,单CPU在某一时间点上只能做一件事。
    CPU在做程序间的高效切换让我们感觉打游戏和听音乐是同时进行的。

    一个程序只有一条执行路径,称为单线程程序。
    一个程序有多条执行路径,称为多线程程序。

什么是线程:
    同一进程内又可以执行多个任务,而这每一个任务就可以看成一个线程。
    线程是程序的执行单元,执行路径。是程序使用CPU的最基本单位。

多线程的意义:
    多线程的存在,不是为了提高程序的执行速读,是为了提高应用程序的使用率。
    程序的执行其实就是在抢CPU的资源,CPU的执行权。
    多个进程在抢资源的时候,其中某一个进行的执行路径比较多,就会有更高的几率抢到CPU的执行权。
    但是不能保证的是哪一个线程在哪个时刻抢到执行权,所以线程的执行有随机性。

并发和并行的区别:
    并发是逻辑上同时发生,指在某一时间内同时运行多个程序。
    并发是物理上同时发生,指在某一时间点同时运行多个程序。

JAVA程序运行原理:
    java命令会启动java虚拟机,启动JVM就等于启动了一个应用程序,也就是一个进程,
    这个进行自动启动一个“主进程”,然后主进程调用某个类的main方法。所以main方法运行在主线程中。

JAVA虚拟机的启动是多线程的,除了主线程,至少还需要垃圾回收线程,否则内存很快就会溢出。

24 个回复

倒序浏览
如何实现多线程?
    线程是依赖进程存在的,应该先创建一个进程出来。
    进程是由系统创建的,应该调用系统功能创建一个进程。
    java不能直接调用系统功能,所以没有办法直接实现多线程程序
    但是java可以调用C/C++写好的程序实现多线程程序。
    由C/C++去调用系统能创建进程,然后由java去调用。
    java再提供一些类供我们使用,这就可以实现多线程了。

回复 使用道具 举报
本帖最后由 Kevin.Kang 于 2015-8-3 17:40 编辑

方式1:继承Thread类
自定义MyThread()方法
  1. package com.kxg_01;
  2. public class MyThread extends Thread {
  3.         @Override
  4.         // 重写run()方法,不是类中的所有代码都需要被线程执行,这个时候,为了区分哪些代码能够被线程执行,
  5.         // java提供了Thread类中的run()方法用来包含那些被线程执行的代码。
  6.         public void run() {
  7.                 for (int i = 0; i < 100; i++) {
  8.                         System.out.println(getName() + ":" + i);//getName()方法是Thread类中获取线程名称
  9.                 }
  10.         }
  11. }
复制代码
创建线程对象并启动
  1. package com.kxg_01;

  2. /*
  3. * 需求:继承Thread实现多线程的程序
  4. *
  5. * 步骤:
  6. *                 1.自定义MyThread类继承Threa类
  7. *                 2.重写Thread类中的run()方法
  8. *                 3.创建对象
  9. *                 4.启动线程
  10. */
  11. public class TreadDemo {
  12.         public static void main(String[] args) {
  13.                 MyThread m1 = new MyThread();
  14.                 MyThread m2 = new MyThread();

  15.                 // m1.run();
  16.                 // m2.run();
  17.                 // 调用run()方法不是开始线程,这样调用相当于调用了一个普通的run()方法

  18.                 // 用start()方法启动线程
  19.                 m1.start();
  20.                 m2.start();
  21.         }
  22. }
复制代码

run()方法封装被线程执行的代码,直接调用是普通方法。
start()方法先启动了线程,然后再由JVM调用该线程的run()方法。


回复 使用道具 举报
获取和设置线程名称:
  1. package com.kxg_01;
  2. public class MyThread extends Thread {

  3.         public MyThread() {
  4.         }

  5. //        定义带参构造方法,Thread类里面有这个带参构造,把参数传递给Thread
  6.         public MyThread(String name) {
  7.                 super(name);
  8.         }
  9.         public void run() {
  10.                 for (int i = 0; i < 100; i++) {
  11.                         System.out.println(getName() + ":" + i);
  12.                 }
  13.         }
  14. }
复制代码
  1. package com.kxg_01;
  2. public class TreadDemo {
  3.         public static void main(String[] args) {
  4.                 MyThread m1 = new MyThread();
  5.                 MyThread m2 = new MyThread();

  6.                 // 通过带参构造定义线程名称
  7.                 // MyThread m3 = new MyThread("广州");
  8.                 // MyThread m4 = new MyThread("深圳");

  9.                 // 通过Thread类中的setName()方法定义线程名称
  10.                 m1.setName("北京");
  11.                 m2.setName("上海");

  12.                 m1.start();
  13.                 m2.start();
  14.         }
  15. }
复制代码




回复 使用道具 举报
设置线程优先级:
  1. package com.kxg_02;

  2. /*
  3. * 设置线程优先级
  4. *                 public final void setPriority(int newPriority)
  5. *
  6. * 注意:       
  7. *                 线程默认优先级是5
  8. *                 线程优先级范围为1-10
  9. *                 优先级高仅仅代表该线程获取的CPU时间片的几率高一些,多次运行才能有好的效果
  10. */
  11. public class TreadDemo {
  12.         public static void main(String[] args) {
  13.                 // 创建线程
  14.                 MyThread m1 = new MyThread();
  15.                 MyThread m2 = new MyThread();

  16.                 // 设置线程名称
  17.                 m1.setName("北京");
  18.                 m2.setName("上海");

  19.                 // 设置线程优先级
  20.                 m1.setPriority(1);
  21.                 m1.setPriority(10);

  22.                 // 启动线程
  23.                 m1.start();
  24.                 m2.start();
  25.         }
  26. }
复制代码



回复 使用道具 举报
设置线程休眠时间:
  1. package com.kxg_03;
  2. public class MyThread extends Thread {
  3.         public void run() {
  4.                 for (int i = 0; i < 100; i++) {
  5.                         System.out.println(getName() + ":" + i);
  6.                         // public static void sleep(long millis):设置休眠时间,单位为毫秒
  7.                         try {
  8.                                 Thread.sleep(1000);
  9.                         } catch (InterruptedException e) {
  10.                                 e.printStackTrace();
  11.                         }
  12.                 }
  13.         }
  14. }
复制代码



回复 使用道具 举报
加入线程:
  1. package com.kxg_04;

  2. /*
  3. * public final void join():等待该线程终止。
  4. *                 别的线程需要等待这个加入的线程执行结束才能执行。
  5. */
  6. public class TreadDemo {
  7.         public static void main(String[] args) {
  8.                 // 创建线程
  9.                 MyThread m1 = new MyThread();
  10.                 MyThread m2 = new MyThread();
  11.                 MyThread m3 = new MyThread();

  12.                 // 设置线程名称
  13.                 m1.setName("北京");
  14.                 m2.setName("上海");
  15.                 m3.setName("广州");

  16.                 // 启动线程
  17.                 m1.start();
  18.                 // 加入线程
  19.                 try {
  20.                         m1.join();
  21.                 } catch (InterruptedException e) {
  22.                         e.printStackTrace();
  23.                 }
  24.                 m2.start();
  25.                 m3.start();
  26.         }
  27. }
复制代码



回复 使用道具 举报
好东西,留着看
回复 使用道具 举报
礼让线程:执行效果就是两个线程你一次,我一次的执行
  1. package com.kxg_05;
  2. public class MyThread extends Thread {
  3.         public void run() {
  4.                 for (int i = 0; i < 100; i++) {
  5.                         System.out.println(getName() + ":" + i);

  6.                         // public static void yield():暂停当前正在执行的线程对象,并执行其他线程。也称为礼让线程
  7.                         Thread.yield();
  8.                 }
  9.         }
  10. }
复制代码



回复 使用道具 举报
本帖最后由 Kevin.Kang 于 2015-8-3 18:22 编辑

守护线程:
  1. package com.kxg_06;

  2. /*
  3. * public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程。
  4. *                 当正在运行的线程都是守护线程时,Java 虚拟机退出。该方法必须在启动线程前调用。
  5. */

  6. public class TreadDemo {
  7.         public static void main(String[] args) {
  8.                 // 创建线程
  9.                 MyThread m1 = new MyThread();
  10.                 MyThread m2 = new MyThread();

  11.                 // 设置守护线程
  12.                 m1.setDaemon(true);
  13.                 m2.setDaemon(true);
  14.                 // 设置线程名称
  15.                 m1.setName("深圳");
  16.                 m2.setName("上海");

  17.                 // 启动线程
  18.                 m1.start();
  19.                 m2.start();

  20.                 // 设置当前运行线程名称
  21.                 Thread.currentThread().setName("北京");
  22.                 for (int i = 0; i < 10; i++) {
  23.                         // Thread.currentThread().getName():当前执行的线程的名称
  24.                         System.out.println(Thread.currentThread().getName() + ":" + i);
  25.                 }
  26.         }
  27. }
复制代码
m1,m2设置称为守护线程,当前运行主线程结束的时候,m1,m2都会随之结束。但已经抢到了执行权,不可能立马结束,会稍微运行一下。


回复 使用道具 举报
中断线程:
  1. package com.kxg_06;

  2. /*
  3. * 中断线程:
  4. *                 public void interrupt()
  5. */

  6. public class TreadDemo {
  7.         public static void main(String[] args) {
  8.                 // 创建线程
  9.                 MyThread m1 = new MyThread();
  10.                 MyThread m2 = new MyThread();

  11.                 // 设置线程名称
  12.                 m1.setName("深圳");
  13.                 m2.setName("上海");

  14.                 // 中断线程,后面的线程还可以继续运行
  15.                 m1.interrupt();
  16.                 // 启动线程
  17.                 m2.start();
  18.         }
  19. }
复制代码



回复 使用道具 举报
线程生命周期:

线程生命周期图解.png (1.93 MB, 下载次数: 24)

线程生命周期图解.png
回复 使用道具 举报
方式2:通过实现Runnable接口的实现类
  1. package com.kxg_07;
  2. /*
  3. * 实现Runnable接口
  4. */
  5. public class MyRunnable implements Runnable {

  6.         @Override
  7.         public void run() {
  8.                 for (int i = 0; i < 100; i++) {
  9.                         System.out.println(Thread.currentThread().getName() + ":" + i);
  10.                 }
  11.         }
  12. }
复制代码
  1. package com.kxg_07;

  2. /*
  3. * 实现Runnable接口
  4. * 步骤:
  5. *                 1.自定义类MyRunnable实现Runnabe接口
  6. *                 3.创建MyRunnable对象
  7. *                 4.创建Thread类的对象,把MyRunnable对象作为构造参数传递
  8. */
  9. public class RunnableDemo {
  10.         public static void main(String[] args) {
  11.                 // 创建对象
  12.                 MyRunnable mr = new MyRunnable();

  13.                 // 设置线程
  14.                 Thread t1 = new Thread(mr);
  15.                 Thread t2 = new Thread(mr);

  16.                 // 设置线程名称
  17.                 t1.setName("深圳");
  18.                 t2.setName("上海");

  19.                 // 启动线程
  20.                 t1.start();
  21.                 t2.start();
  22.         }
  23. }
复制代码



回复 使用道具 举报
方式2好处:
1.可以避免由于java单继承带来的局限性
2.适合多个相同程序的代码去处理同一个资源的情况,
把线程和程序的代码,数据有效分离,较好的体现了面向对象的设计思想。

回复 使用道具 举报
判断线程是否有问题的标准
    1.是否是多线程环境
    2.是否有共享数据
    3.是否有多条语句操作共享数据

回复 使用道具 举报
{:2_31:}!!!!!!!!!!!!!!!!!!!!!
回复 使用道具 举报
线程的状态转换图及常见执行情况:

线程的状态转换图及常见执行情况.jpg (1.93 MB, 下载次数: 27)

线程的状态转换图及常见执行情况.jpg
回复 使用道具 举报
方式3:实现Callable接口,需要和线程池结合使用
实现类:
  1. package com.kxg_06;
  2. import java.util.concurrent.Callable;

  3. /*
  4. * Callable<V>:带泛型的接口
  5. *                 接口中只有一个方法:V call()
  6. *                 接口中的泛型是call()方法的返回值类型
  7. *
  8. */
  9. public class MyCallable implements Callable {

  10.         @Override
  11.         public Object call() throws Exception {
  12.                 for (int i = 0; i < 100; i++) {
  13.                         System.out.println(Thread.currentThread().getName() + ":" + i);
  14.                 }
  15.                 return null;
  16.         }
  17. }
复制代码
测试类:
  1. package com.kxg_06;

  2. import java.util.concurrent.ExecutorService;
  3. import java.util.concurrent.Executors;

  4. public class MyCallableDemo {
  5.         public static void main(String[] args) {
  6.                 // 创建线程池对象
  7.                 ExecutorService pool = Executors.newFixedThreadPool(2);

  8.                 // 添加Callable实现类
  9.                 pool.submit(new MyCallable());
  10.                 pool.submit(new MyCallable());

  11.                 // 结束线程池
  12.                 pool.shutdown();
  13.         }
  14. }
复制代码



回复 使用道具 举报
。。。。。。。。。。。。。。。。。。
回复 使用道具 举报
更加深刻懂了多线程。
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马