小强的java练级记之线程

一、进程、线程、多线程的定义:

 

进程、线程、多线程的定义:

   

       进程:正在运行的程序,负责了这个程序的内存空间分配,代表了内存中的执行区域。

           (一个正在运行的QQ应用程序)

       线程:就是在进程中负责一个执行路径。

           QQ应用程序的视频、聊天、语音)

       多线程:就是一个进程中多个执行路径同时执行

           (同时使用QQ的视频和打字功能)

          

       面试题:一个java程序执行过程中必备的几个线程?

              两个

              1、主线程

              2、垃圾回收器线程

 

二、创建线程的步骤:

创建线程的步骤:

       1、继承Thread类(方式一)java.lang.Thread

       2、重写run方法

       3、创建该线程类对象

       4、调用start()方法。

//1、继承Thread

public class Demo2 extends Thread{

    //2、重写run方法

    @Override

    public void run() {

      

       for(int i=0; i<100; i++) {

           System.out.println("Demo2"+":"+i);

       }

    }

    public static void main(String[] args) {

       //3、创建该线程类对象

       Demo2 demo2 = new Demo2();

       //4、调用start()方法。

       demo2.start();

      

       for(int i=0; i<100; i++) {

           System.out.println("main"+":"+i);

       }

    }

}

 

三、线程的生命周期:

 

四、线程的安全问题:

引出线程安全的根本原因:

       1、存在两个或两个以上的线程

       2、多个线程操作了共享资源。

 

      解决方案:

             1、使用同步代码块。

             synchronized(锁对象)

             {

                    同步代码区域;

              }

             2、使用同步函数

                  a.非静态同步函数的锁对象是this对象,静态函数对象是当所属类的class文件对象。

                 b.同步函数的锁对象是固定的,无法更改。同步函数锁的范围更大,并不是只是锁住共享的代码块。

     所以推荐用同步代码块的方式。

      使用同步时候需要注意的问题:

             1、锁对象可以是任意的对象(必须得是共享对象)

             2、锁对象必须是多个线程

             3、线程调用了sleep方法是不会被释放锁对象的。

             4、只有会遇到线程安全问题时候,才会使用锁机制。否则会影响执行效率问题。

 

五、线程的安全需求案例:

案例一、模拟车站卖票过程

class SaleTickets extends Thread {

    static int num = 50;

    public SaleTickets(String name) {

       super(name);

    }

 

    public void run() {

       while (true) {

           synchronized ("") {

              if (num > 0) {

                  System.out.println(Thread.currentThread().getName()

                         + "卖了第 " + num + " 张票");

                  num--;

              } else {

                  System.out.println("售罄了!");

                  break;

              }

           }

       }

    }

}

public class Demo5 {

 

    public static void main(String[] args) {

       SaleTickets st1 = new SaleTickets("窗口一");

       SaleTickets st2 = new SaleTickets("窗口二");

       SaleTickets st3 = new SaleTickets("窗口三");

 

       st1.start();

       st2.start();

       st3.start();

    }

}

案例二、夫妻俩去银行取钱

class DrawMoney extends Thread {

 

    static int money = 5000;

 

    public DrawMoney(String name) {

       super(name);

    }

 

    public void run() {

       while (true) {

           synchronized ("") {

              if (money > 0) {

                  System.out.println(Thread.currentThread().getName()

                         + "取了100元," + "还剩下" + money);

                  money -= 100;

              } else {

                  System.out.println("别败家了,没钱了!");

                  break;

              }

           }

       }

    }

 

}

public class Demo6 {

 

    public static void main(String[] args) {

 

       DrawMoney dt1 = new DrawMoney("丈夫");

       DrawMoney dt2 = new DrawMoney("妻子");

 

       dt1.start();

       dt2.start();

    }

 

}

六、守护线程:

/**

    守护线程:(后台线程)

       当一个java应用只剩下守护线程的时候,那么守护线程马上结束。

 */

class MyThread extends Thread {

   

    public MyThread(String name) {

       super(name);

    }

   

    @Override

    public void run() {

       for(int i=1; i<=100; i++) {

           System.out.println(this.getName()+"文件已经下载了"+i+"%");

           try {

              Thread.sleep(100);

           } catch (InterruptedException e) {

              e.printStackTrace();

           }

       }

       System.out.println("文件下载完毕");

    }

}

public class Demo1 extends Thread{

   

   

   

    public static void main(String[] args) {

      

       MyThread mt = new MyThread("守护线程");

       System.out.println(mt.isDaemon());

       mt.start();

      

       for(int i=1; i<=100; i++) {

            System.out.println(Thread.currentThread().getName()+":"+i);

       }

    }

}

 

七、线程让步:

/**

    线程让步:(join关键字)

       案例:妈妈让你打酱油。

 */

class Mother extends Thread{

   

    public Mother(String name) {

       super(name);

    }

   

    @Override

    public void run() {

      

       System.out.println("妈妈在洗菜");

       System.out.println("妈妈在切菜");

       System.out.println("妈妈在发现没酱油了,让儿子去打酱油。");

       //这个时候儿子应该去打酱油

       Son s = new Son("儿子");

       s.start();

       try {

           s.join();//这句话的意思不是儿子调用join,而是妈妈这个线程指定这个时刻先执行儿子线程。

       } catch (InterruptedException e) {

           e.printStackTrace();

       }

       System.out.println("妈妈在炒菜");

       System.out.println("全家人坐在一起吃饭。");

    }

}

class Son extends Thread {

   

    public Son(String name) {

       super(name);

    }

   

    @Override

    public void run() {

      

       System.out.println("儿子走出家门");

       System.out.println("儿子打酱油路上");

       try {

           Thread.sleep(1000);

       } catch (InterruptedException e) {

           e.printStackTrace();

       }

       System.out.println("儿子打酱油归来");

    }

}

public class Demo2 {

   

    public static void main(String[] args) {

      

       Mother m = new Mother("妈妈");

      

       m.start();

    }

}

 

八、线程通讯问题:

/**

        线程通讯问题:(重点以及难点)

           当线程完成了一个任务的时候,需要通知另外一个线程去做其他事情。

          

        wait():执行wait方法,线程会让该线程进入以锁对象建立的线程池中等待。

        notify():执行notify方法,线程会唤醒以锁对象建立的线程池中等待的线程中的一个。

        notifyAll():把所有的线程都唤醒。

 */

class Product {

   

    String name;

    int price;

   

    boolean flag = false //是否已经有产品生产

}

class Producer extends Thread {

   

    int i = 0;

    Product p;

   

    public Producer(Product p) {

       this.p = p;

    }

    @Override

    public void run() {

       while(true) {

           synchronized (p) {

              if(!p.flag) {

                  if(i%2==0) {

                     p.name = "摩托车";

                     p.price = 3500;

                     System.out.println("生产者生产了:"+p.name+",价格:"+p.price);

                  }else{

                     p.name = "电动车";

                     p.price = 1500;

                     System.out.println("生产者生产了:"+p.name+",价格:"+p.price);

                  }

                  i++;

                  p.flag = true; //有产品已经被生产;

                  p.notify();  //唤醒等待的消费线程。

              }else{

                  try {

                     p.wait();  //这个时候原本已经有产品被生产,所以该线程要进入等待。

                  } catch (InterruptedException e) {

                     e.printStackTrace();

                  }

              }

           }

       }

    }

   

}

class Consumer extends Thread {

   

    Product p;

   

    public Consumer(Product p) {

       this.p = p;

    }

   

    @Override

    public void run() {

      

       while(true) {

           synchronized (p) {

              if(p.flag) {

                  System.out.println("消费者消费了价格为"+p.price+""+p.name);

                  p.flag = false;

                  p.notify();//唤醒等待的生产线程

              }else {

                  try {

                     p.wait();

                  } catch (InterruptedException e) {

                     e.printStackTrace();

                  }

              }

           }

       }

    }

   

}

public class Demo3 {

   

    public static void main(String[] args) {

      

       Product p = new Product();

       Producer producer = new Producer(p);

       Consumer consumer = new Consumer(p);

      

       producer.start();

       consumer.start();

    }

 

}

 

九、停止线程:

/**

    停止线程:

       1.我们停止一个线程一般会配合你一个变量去控制。

       2、如果我们停止的是一个等待状态下的线程,那么需要配合interrupt方法去使用.

 */

public class Demo4 extends Thread{

   

    boolean flag = true;

    int i = 0;

   

    public Demo4(String name) {

       super(name);

    }

    @Override

    public synchronized void run() {

       while(flag) {

           try {

              this.wait();

           } catch (InterruptedException e) {

              System.out.println("抛出了一个异常:"+e);

           }

           System.out.println(Thread.currentThread().getName()+":"+i);

           i++;

       }

    }

   

    public static void main(String[] args) {

      

       Demo4 d = new Demo4("Genuine");

       d.start();

      

//     for(int i=0; i<100; i++) {

//         //i80的时候我想要停止这个自定义线程。

//         if(i == 80) {

//            d.flag = false; //方式一

//         }

//         System.out.println(Thread.currentThread().getName()+":"+i);

//     }

       for(int i=0; i<100; i++) {

           //i80的时候我想要停止这个自定义线程。

           if(i == 80) {

              d.interrupt();  //中断一个在等待的线程状态。并且抛出一个interrupt异常。

           }

           System.out.println(Thread.currentThread().getName()+":"+i);

       }

    }

 

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值