黑马程序员--Java学习日记之总结复习(多线程和设计模式)

时间:2022-11-20 16:22:17

                                                                      ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一,进程和线程的概念: 
  要了解"线程",必须先了解一下"进程": 
  什么是进程:
  1.对于"操作系统"而言,每个独立运行的程序就是独立的"进程";
  2."操作系统"会分别针对每个"进程"分配一块独立的内存空间;
  --什么是多进程:
  1."操作系统"可以同时维护多个"应用程序"的执行。
  2.每个应用程序都交由操作系统管理,在某个时间点上,会有一个应用程序被操作系统分配给CPU去执行,执行一会后,会被操作系统
         终止执行,并交由另一个"应用程序"继续执行。由于转换非常快,CPU的运算速度也非常快,这就让我们感觉好像是多个应用程序在
         同时执行一样。
       3.多进程的意义:
      1).方便了我们用户的使用。我们可以同时启动多个程序,一边听歌,一边上网,一边下载;
        2).充分的利用CPU资源;
  什么是线程:
  1.线程是由一个"进程"的内部启动的,可以脱离于"主进程"而独立运行的一块代码;
  2.一个线程一旦启动,将和"主进程"并行运行,一起面对操作系统,抢占系统资源;
  3.一个"进程"可以启动多个"线程";
  --什么是多线程:
  1.一个进程可以同时启动多个线程去单独运行;这个程序就是一个多线程程序;
  2.多线程的意义:
  1).可以使我们的应用程序"同时"运行多个非常复杂的代码;
  2).使我们的程序不用等待那些代码的执行完毕,就可以继续获得执行;
  3).充分的利用了CPU的资源;
  
  什么是"并行"和"并发":
  1."并行"是指逻辑上一起在执行,它强调的是在"同一段时间内"一起运行的程序;
  2."并发"是指物理上的抢占同一资源。它强调的是在"同一时刻时"一起抢占系统的某个共享资源;
二, 实现线程的:
                                                                                                                                方式一
  实现步骤:

  1.自定义一个线程类,要继承自Thread;
  2.重写Thread中的run()方法;将要在线程中执行的代码写到这里;
  3.启动线程:
  1).实例化一个我们自定义的线程类;
  2).调用它的start()方法;启动线程;
 public class Demo {  
02. public static void main(String[] args) {
03. MyThread t1 = new MyThread();
04. MyThread t2 = new MyThread();
05.
06. // t1.run();//相当于普通的方法调用,不是启动一个线程
07. // t2.run();//相当于普通的方法调用,不是启动一个线程
08.
09. t1.start();
10. t2.start();
11.
12. for(int i = 0;i < 100;i++){
13. System.out.println("主进程 i = " + i);
14. }
15.
16. //尝试再次启动t1
17. // t1.start();//运行时异常。不能多次调用start(),否则抛出异常:java.lang.IllegalThreadStateException
18. }
19.}


  
   注意:
  1.一个线程类,可以实例化多个对象,并分别启动。也就意味着多个线程同时运行;
  2.一个线程对象,只能调用一次start,不能重复调用。否则抛出异常:java.lang.IllegalThreadStateException

  3.只用调用start()才是启动线程。run()方法内的代码会以一个线程的方式去运行;

一.线程实现方式:
 1.继承Thread类;
 2.实现Runnable接口;

二.设置获取线程的名称:
 getName()和setName(String name);
三.设置获取线程的优先级:
 getPriority()和setPriority(int n);
 线程的优先级范围:1--10(从低到高)
四.线程的休眠:sleep(long m):休眠到指定的m毫秒后,将自动醒来;
   加入:join();
   礼让:yield():退回到"就绪状态",可能会被操作系统重新分配;
   守护:setDaemon(boolean on):on为true,守护线程。主进程结束,守护线程也结束,但不会立即结束,会有一个小缓冲;
   中断:stop()(过时了)
         interrupt():线程一定要处于:Object-->wait();Thread-->sleep();Thread--join()三种状态之一时,才能触发此异常;
五.解决并发性问题:
 1.使用关键字:synchronized
 2.synchronized可以修饰一个代码块:同步代码块
          synchronized可以修饰一个方法:同步方法
 3.静态的方法可以被synchronized修饰。
          静态的方法内部也可以包含synchronized的代码块,但一般锁定是某个类的class对象。

一.JDK5的Lock锁:
 Lock lock = ....;
 lock.lock();
 try{
  //需要同步的代码
 }finally{
  lock.unlock();
 }
二.死锁的现象:
 见图
三.生产和消费者问题:
 1.单生产和单消费;
 2.在共享资源中:
  1).wait():让访问的线程等待(释放锁)
  2).notify()和notifyAll():唤醒;
四.线程组:
 1.任何的线程都有一个默认的线程组;
 2.可以自行指定线程组:
  1).实例化一个线程组;
  2).通过Thread的构造方法去指定线程组;
 3.可以统一对线程组内的所有线程执行统一操作;
五.线程池:JDK5后出现:
 1.Executors类的
  public static ExecutorService newCachedThreadPool()
  public static ExecutorService newFixedThreadPool(int nThreads)
  public static ExecutorService newSingleThreadExecutor()
 2.调用ExecutorService的:
  Future<?> submit(Runnable task)
   <T> Future<T> submit(Callable<T> task)


 
六.JDK5的多线程的实现方式(多线程实现的方式3)
 1.自定义类,实现Callable接口;
 2.重写call()方法;(有返回值了)
 3.启动:
  使用线程组的方式启动线程;
  
七.定时器:
 1.TimersTask(抽象类):定义任务
  1).自定义类,继承自TimerTask;
  2).重写run()方法;
 2.Timer类:
  构造方法:Timer();
  执行任务:
  public void schedule(TimerTask task, long delay):在delay毫秒后执行一次;
  public void schedule(TimerTask task,long delay,long period):在delay毫秒后开始执行,并每间隔period毫秒后会重复执行;

八.设计模式:
 1.简单工厂模式:
  1.定义具体产品类;
  2.定义工厂类;
  3.在工厂类中提供针对每个产品的get方法,或者提供一个方法获取所有产品;
  优点:前端无需直接面对具体的产品,只需要通过工厂获取具体产品就可以;
  缺点:每增加一个新产品,都要修改工厂类;
 2.工厂方法模式:
  1.定义产品的接口;
  2.定义工厂的接口;
  3.增加一个产品时,定义产品类,实现"产品接口",定义工厂类,实现"工厂接口"。
  优点:新增产品时,对原类无需任何修改;
  缺点:类太多;
 3.单例模式--饿汉式:
  class Student{
   prviate static Student stu = new Student();
   private Student(){
   }
   public static Student getStudent(){
    return stu;
   }
  }
 4.单例模式--懒汉式:
  class Student{
   private static Student stu = null;
   private Student(){
   }
   public synchronized static Student getStudent(){
    if(stu == null){
     stu = new Student();
    }
    return stu;
   }
  }

有时候我们还需要结合interrupt()方法来结束一个线程,见如下例子:
package com.heima.exam;

class StopThreadTest {
 public static void main(String[] args) {
  
  ThreadInStop t1 = new ThreadInStop();
  t1.start();
  int index = 0;
  
  while(true) {
   if(index++ == 500){
    t1.stopThread();
    t1.interrupt();
    break;
   }
   System.out.println(Thread.currentThread().getName());
  }
  System.out.println("main() exit");
 }
}

class ThreadInStop extends Thread {
 
 private boolean bStop = false;
 
 public synchronized void run() {
  
  while(!bStop) {
   try {
    wait();
   } catch(InterruptedException e) {
    if(bStop) {
     return;
    }
   }
   System.out.println(getName());
  }
 }
 
 public void stopThread() {
  bStop = true;
 }
}