程序:一些静态代码
进程:正在运行的程序
线程:一个进程的的一条执行路径 ,每个线程都会拥有独立的运行栈和程序计数器

一个java应用,至少3个线程,

  1. main()主线程
  2. gc()垃圾回收线程
  3. 异常处理线程,放生异常,会影响主线程

并行:CPU同时执行多个任务
并发:一个CUP同时执行多个任务

创建多线程的方式:

1. 第一种

  1. 继承Thread
  2. 重写run()方法
  3. 创建子类对象
  4. 子类对象调用start();他来调用run();

    2. 第二种

  5. 实现Runnable

  6. 实现run() ;方法
  7. 创建实现类对象
  8. 创造Thread类,并将实现类传递到构造器中
  9. 调用thread的start()方法

    第三种

  10. 实现Callable接口 JDK 5.0新增

  11. 重写call()方法 ,执行到操作
  12. 创建Callable实现对象
  13. 创建Futuretask对象,将Callable实现对象传入构造方法
  14. 将Futuretask对象传入Thread()对象,并调用start
  15. 需要返回值就使用Futuretask对象,的get()方法,获取的就是call的返回值

    第四种:线程池

  16. 提供指定数量的线程池:ExecutorService service = Executors.newFixedThreadPool(10); 线程池数量

  17. 设置线程池属性:ThreadPoolExecutor server = (ThreadPoolExecutor)service ;
  18. 指定线程的操作,实现Runnable(使用service.execute(实现类))或者Callable(使用service.submit(实现类))接口的实现类
  19. 关闭线程池:service.shutdown();


    第三种比第二种好在哪:
    call有返回值,可以抛出异常,被外面操作捕获.
    callable支持泛型

    代码如下 :

    1. **
    2. * 线程的四种创建方式
    3. */
    4. public class CreateThreadDemo {
    5. public static void main(String[] args) {
    6. // 第一种
    7. MyThread1 t1 = new MyThread1();
    8. t1.start();
    9. MyThread1 t2 = new MyThread1();
    10. t2.start();
    11. // 第一种的匿名子类的匿名对象的创建
    12. new Thread() {
    13. @Override
    14. public void run() {
    15. super.run();
    16. }
    17. }.start();
    18. // 第二种
    19. MyThread2 thread2 = new MyThread2();
    20. Thread t3 = new Thread(thread2);
    21. t1.start();
    22. Thread t4 = new Thread(thread2);
    23. t2.start();
    24. // 第三种
    25. MyThread3 t = new MyThread3();
    26. FutureTask futureTask = new FutureTask(t);
    27. new Thread(futureTask).start();
    28. try {
    29. //get()返回值就是call方法的返回值
    30. Object sun = futureTask.get();
    31. System.out.println("总和为:" + sun);
    32. } catch (InterruptedException e) {
    33. e.printStackTrace();
    34. } catch (ExecutionException e) {
    35. e.printStackTrace();
    36. }
    37. // 第四种
    38. ExecutorService service = Executors.newFixedThreadPool(10);
    39. ThreadPoolExecutor service1 = (ThreadPoolExecutor) service; //可以使用server1来设置线程池的属性
    40. //service.submit(实现Callable的对象);
    41. //service.execute(实现Runnable对象);
    42. service.shutdown();
    43. }
    44. }
    45. // 第一种
    46. class MyThread1 extends Thread {
    47. @Override
    48. public void run() {
    49. //要开启线程执行的语句
    50. }
    51. }
    52. // 第二种
    53. class MyThread2 implements Runnable {
    54. @Override
    55. public void run() {
    56. //要开启线程执行的语句
    57. }
    58. }
    59. // 第三种
    60. class MyThread3 implements Callable {
    61. @Override
    62. public Object call() throws Exception {
    63. // 语句
    64. int sun = 0;
    65. for (int i = 0; i < 20; i++) {
    66. sun += i;
    67. System.out.println(i);
    68. }
    69. return sun;
    70. }
    71. }

比较1和2的:优先使用第二种

  • 方法1.如果继承Thread,那么他就无法再去继承其他的父类.
  • 实现更适合处理多个线程共享数据的情况
  • Thread 本身也是实现Runnable接口

Thread线程常见方法

  • start(): 启动当前线程,调用run()方法
  • run(): 线程要执行的操作
  • currentThread(): 静态 放回当前执行的线程
  • getName(): 获取当前线程的名字
  • setName(): 设置线程的名字
  • yield(): 释放当前cpu执行权
  • join(): 在线程A中调用B的join(),A进入阻塞状态,等B执行完成,在执行A.
  • stop(): 过时了,强制结束线程
  • sleep(long millis): 静态 让线程睡眠millis休息毫秒,时间内是阻塞状态
  • isAlive(): 判断当前线程是否存活

线程优先级

  • MAX_PRIORITY:10
  • MIN_PRIORITY:1
  • NORM_PRIORITY:5 默认优先级
  • setPriority(int p); 设置优先级
  • getPriority(); 获取线程优先级

线程的几种状态

  • 新建:Thread类及其子类声明对象并创建,线程处于新建状态
  • 就绪:新建状态被start()后,等待CPU时间片,具备执行条件,没有分配到CPU资源
  • 运行:获得CPU资源
  • 阻塞:人为或者执行输入输出操作,让CPU并临时中止自己的执行
  • 死亡:完成全部的工作或者线程提前强制中止或者出现异常导致结束

线程安全:(例题又一个简单的买票软件)

  1. 一个线程在操作共享数据是,其他线程也进来操作 <br />** 但是加了同步,只能一个线程操作,其他线程等待,相对于单线程,效率低**<br /> 解决问题:

1.监听器
1.synchronized(同步监视器){
//需要被同步的数据,操作共享数据的代码
}

  • 同步监视器:锁, 任何一个类的对象,都可以当作锁
  • 多个线程共用一个锁就可以解决安全问题
  • 实现Runnable接口可以使用,this来当锁
  • 继承Thread可以使用当前类来充当锁
  • synchronized解决安全问题,操作同步代码,但是只能有一个线程参与,相当于单线程的过程

      2.同步方法
    
  • 将操作共享数据的代码封装到方法中

  • 实现Runnable在方法中使用synchronized关键字,锁this当前对象
  • 继承Thread方法上加上static synchronized,锁还是当前类,类名.class

       3.lock锁 JDK5.0新加
    
  • 创建ReentrantLock对象

  • 在需要同步代码前面加对象.lock();
  • 结束加上lock.unlock();

      lock和synchronized的区别:两者都可以解决线程安全问题,synchronized执行完对应的同步代码,自动释放锁,lock要手动开启,和手动结束.lock锁,JVM将花费更少的时间来调度线程,性能更好.有更好的扩展性(提供了更多的子类)
    

    死锁(例题中有案例)

    不同的资源分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就会形成线程的死锁
    解决方法:专门的算法,减少同步资源的定义,尽量避免嵌套同步

线程的通信

  • wait() 执行方法,但前线程进入阻塞状态,会释放锁
  • notify:执行方法,会唤醒被wait()的一个线程,多个线程被wait,就唤醒优先级高的
  • notifyAll():执行方法,唤醒所有被wait的线程

上面3个必须使用在同步代码和同步方法中,调用者必须是同步代码块和同步方法的监视器(锁)
他们定义在Object类中,因为监视器可以是任意对象,任意对象一定定义在Object中

sleep() 与 wait()异同

相同点:都可以让线程进入阻塞状态
不同点:sleep()定义在Thread, wait()定义在Object
sleep()任何情况都可以执行, wait()只能在同步代码块,和同步方法中.
sleep()不释放锁释放cup执行权, wait()释放锁释放cpu执行权,