黑马程序员——JAVA之多线程

来源:互联网 发布:淘宝一元拍网址 编辑:程序博客网 时间:2024/04/30 22:44

------- http://www.itheima.com" target="blank">android培训http://www.itheima.com"target="blank">java培训、期待与您交流!

 

基础知识概述

 

<span style="font-family:Microsoft YaHei;font-size:14px;">package com.hyx; /* 一、关于进程和线程 * 进程:正在运行的程序,是系统进行资源分配和调用的独立单位;每一个进程都有它自己的内存空间和系统资源。 * 线程:是进程中的单个顺序控制流,是一条执行路径;一个进程如果只有一条执行路径,则称为单线程程序;一个进程如果有多条执行路径,则称为多线程程序。 *  * 二、关于并行和开发 * 并行:前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。 * 并发:后者是物理上同时发生,指在某一个时间点同时运行多个程序。 *  * 三、Java程序的运行原理: *     由java命令启动JVM,JVM启动就相当于启动了一个进程;接着由该进程创建了一个主线程去调用main方法。 *  *   Java虚拟机的启动也是多线程的:至少有两个,主线程和垃圾回收线程。启动垃圾回收线程的原因是为了防止内存溢出。 *  * 四、实现多线程的三种方式: *   1.继承Thread类: * 步骤:自定义类继承Thread类--->自定义类重写run()方法--->创建自定义类对象--->调用start()方法启动线程 *   2.实现Runnable * 步骤:自定义类是想Runnable接口--->自定义类重写run()方法--->创建自定义类对象;创建Thread类对象并将自定 * 义类对象作为实参传入Thread类中--->调用Thread类的start()方法启动线程new Thread(new MyThread()).start(); *    3.实现Callable接口(JDK5) *     * 五、该类为什么要重写run()方法呢? *         不是类中所有的代码都需要被线程执行的;为了区分哪些代码能够被执行,java提供了Thread类中的run()方法用来包含那些被线程执行的代码。 *  * 六、同步有三种方式:1.同步代码块    2.同步方法  3.Lock锁 *  * 七、面试题:run()与start()的区别? *    run()方法:仅仅是封装被线程执行的代码,直接调用是普通方法; *    start()方法:首先启动了线程,然后再由JVM去调用该线程的run()方法。 *  * 八、线程常用方法: * 1.线程名称: *setName(String n):设置线程名称: *    getName():获取线程名称; *2.线程优先级:低-->高:1--10。默认:5 *setPriority(int n):设置优先级。如果不在1--10的范围内,则抛出异常; *getPriority():获取线程的优先级; *3.线程休眠: *sleep(int n):静态方法。单位:毫秒; *4.线程的加入: *join():普通方法。其它线程会等待此线程执行完毕再执行; *5.线程的礼让: *yield():静态方法。退回到"就绪"状态。很可能会被操作系统再次分配运行; *6.守护线程: *setDaemon(boolean n):如果true,则为"守护线程"。当主线程结束时,守护线程也会跟着结束(但不会立即结束,会有个小缓冲) *7.线程的中断: *stop():不建议使用。 *interrupt():在线程内部,当处于以下三种情况: *Object-->wait(): *Thread-->join(): *Thread-->sleep(): *             会触发一个异常的产生; * 九、线程的生命周期 * 创建--》就绪--》运行--》死亡; *当一个线程start()后,线程不会被立即执行,其出于就绪状态,等待CPU分配其运行空间。 * 十、同步 * 1.同步代码块:synchronized(被锁的对象){} * 2.同步方法:public synchronized void show(){} * A、静态方法内,可以包含“同步代码块”,但被锁的对象不能使用this,一般是使用此类的Class对象 *     B、静态方法,可以被声明为“同步方法”。 *      3.JDK5的Lock锁: *      Lock l = ...; *      l.lock();//加锁 *      try{//同步的代码 *      }finally{ *      l.unlock();//释放锁 *      } *  十一、设计模式:1.简单工厂模式:  2.工厂方法模式  3.单例模式:1).饿汉式;2).懒汉式; *  十二、线程池: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) *      */ public class MyThread {}</span>


 

 

通过代码演示加强认知

  一、线程实现方式一:继承Thread类

<span style="font-family:Microsoft YaHei;font-size:14px;">class Test{public static void main(String[] args){//创建线程对象Thread1 t = new Thread1();Thread1 t1 = new Thread1();//Thread1 t2 = new Thread1();//设置线程名称t.setName("轻水");t1.setName("青璃");// t2.setName("琉夏");//调用start()方法启动线程t.start();t1.start();//t2.start();//主方法中的程序for (int i = 0; i < 100; i++) {System.out.println(i);}}}</span>


 

<span style="font-family:Microsoft YaHei;font-size:14px;">package cn.itcast;public class Thread1 extends Thread {public void run() {for (int i = 0; i < 50; i++) {System.out.println(this.getName()+"["+i+"]");try {</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">//休眠一秒钟</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">Thread1.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}</span>


 

 

二、多线程实现方式二

 

 

<span style="font-family:Microsoft YaHei;font-size:14px;">/* * 线程实现Runnable(建议使用) * 1.自定义实现Runnable接口; * 2.重写run()方法; * 3.启动线程: * 1).实例化我们自定义类的对象; * 2).实例化一个Thread对象,将我们的自定义对象作为参数传递给Thread的构造方法; * 3).调用Thread对象的start()方法启动线程 *  * class Thread{ * private Runnable target = null; * public Thread(){ * } * public Thread(Runnable runnable){ * this.target = runnable; * } * public void start(){ * if(this.target == null){ * run(); * }else{ * target.run(); * } * } * public void run(){ * System.out.println("a"); * } * } */public class Demo {public static void main(String[] args) {MyRunnable myRun = new MyRunnable();Thread t = new Thread(myRun);t.start();for(int k = 0 ;k < 100 ; k++){System.out.println("k = " + k);}}}</span>

 

<span style="font-family:Microsoft YaHei;font-size:14px;">public class MyRunnable implements Runnable {@Overridepublic void run() {for(int i = 0;i < 100 ; i++){System.out.println("i = " + i);}}}</span>


 

三、使用同步解决并发访问的问题

 

 

<span style="font-family:Microsoft YaHei;font-size:14px;">/* * 使用同步解决并发访问的问题: *  * 1.在共享资源上(一般是一些方法)使用关键字:synchronized * 2.作用:当一个线程访问时,其它线程全部列队等待;这种机制保证了这个方法在同一时刻 *       只能被一个线程访问; * 3.synchronized语法: * 1.同步代码块: * synchronized(被锁的对象){ * //同步代码 * } *  注:被锁的对象:当一个线程访问此段代码时,会将这个对象中所有的"同步代码块"和"同步方法"加锁, *     也就意味着,一个线程访问一段同步代码块,其它线程不能访问"被锁对象"的其它"同步代码块"和"同步方法"; */public class Demo {public static void main(String[] args) {//1.实例化一个票池;Tickets tic = new Tickets();//2.实例化三个线程,模拟三个窗口售票MyThread t1 = new MyThread(tic);MyThread t2 = new MyThread(tic);MyThread t3 = new MyThread(tic);//3.设置线程名称t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");//4.启动线程t1.start();t2.start();t3.start();}}</span>


 

 
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.TreeSet;public class MyThread extends Thread{private Tickets tic;private int count;private TreeSet<Integer> tree = new TreeSet<>();public MyThread(Tickets t){this.tic = t;};public void run() {while(true){int t = this.tic.getTicket();if(t > 0){//System.out.println(this.getName() + " 抢到票:" + t);tree.add(t);}else{//System.out.println("没票了,不抢了");break;}}System.out.println(this.getName() + " 共抢到 : " + tree.size() + " 张票,明细:" + tree);}}</span>


 

  

<span style="font-family:Microsoft YaHei;font-size:14px;">public class Tickets {private int ticketNo = 100;public int getTicket(){//窗口1synchronized (this) {if(this.ticketNo > 0){//窗口1return this.ticketNo--;//窗口1}else{return 0;}}}}</span>


 

 

 

四、单例设计模式面试题

 

 

<span style="font-family:Microsoft YaHei;font-size:14px;">/*单例设计:饿汉式、懒汉式重点:懒汉式  面试题:1.问:懒汉式和饿汉式有什么不同?     答;懒汉式的特点在于实例的延迟加载。 2.问:懒汉式的延迟加载有没有问题?答:有,如果多线程访问时会出现安全问题。3.问:怎么解决?答:可以通过加同步来解决。4.问:加同步的方式?答:用同步代码块可以,但效率有点低;可以用双重判断的方式提高效率。5.加同步的时候使用的锁是:该类所属的字节码文件*///饿汉式class Single{private static final Single s = new Single();private Single(){}public static Single getInstance(){return s;}}//懒汉式class Single {private static Single s =null;private Single(){}public static Single getInstance(){if (s==null){synchronized(Single.class){if(s==null)s = new Single();}}return s;}}</span>


 

0 0