多线程         
(1)就是应用程序有多条执行路径。 
        进程:就是正在运行的程序。 
        线程:就是进程的执行路径,执行单元。 
         
         
(2).如何使用多线程(掌握) 
        A:方式1 继承Thread类。 
                        a:创建类继承Thread类 
                        b:重写Thread类的run()方法。 
                                run()方法里面才是封装线程的代码。 
                        c:通过调用start()方法启动线程并调用run()方法。<<<start():第一,让线程启动。第二,自动调用run()方法。>>> 
        代码体现: 
 
 
public class MyThread extends Thread { 
        @Override 
        public void run() { 
                for (int x = 0; x < 100; x++) { 
                        System.out.println(getName()+"---hello" + x); 
                } 
        } 
} 
 
main(){ 
 
        MyThread my1 = new MyThread(); 
        MyThread my2 = new MyThread(); 
 
        my1.setName("用友"); 
        my2.setName("金蝶"); 
 
        my1.start(); 
        my2.start(); 
} 
 
................... 
        B:方式2        实现Runnable接口 
                        a:创建一个类实现Runnable接口 
                        b:重写run()方法 
                        c:创建实现类对象,并把它作为参数传递给Thread类的构造方法,创建Thread对象 
                        d:通过Thread的对象执行 
        代码体现: 
 
public class MyRunnable implements Runnable{ 
 
        @Override 
        public void run(){ 
         
                for(int i=0;i<100;i++){ 
                        System.out.println(Thread.currentThread().class+"---"+i); 
                } 
        } 
 
} 
main(){ 
 
        MyRunnable my = new MyRunnable(); 
 
        Thread t1 = new Thread(my); 
        Thread t2 = new Thread(my); 
 
        t1.setName("乔峰"); 
        t2.setName("慕容复"); 
 
        t1.start(); 
        t2.start(); 
} 
 
1.多线程        2.共有资源同步多线程        3.解决错误输出(加锁)        4.均匀输出 
<<<既然有了继承Thread类的方式,为什么还要有实现Runnable接口的方式? 
 * A:避免的单继承的局限性 
 * B:实现接口的方式,只创建了一个资源对象,更好的实现了数据和操作的分离。 
 * 一般我们选择第二种方式。>>> 
<<< 实现了Runnable接口的类没有start()方法,而我们启动线程必须调用start()方法。 
又由于,start()方法只有Thread类有。所以,我们就考虑这个把该类转换成Thread类。>>> 
................... 
(3)线程的随机性原理 
                多个程序其实是CPU的在做着高效切换执行的。 
 
(4)线程的生命周期(面试题 画图自己补齐) 
                新建 
                就绪 
                运行 
                阻塞 
                死亡 
 
(5)线程安全问题 
                A:卖票案例 
 
                B:为什么有问题 
                        a:有共享数据 
                        b:共享数据被多条语句操作 
                        c:在多线程环境中 
 
(6)线程安全问题的解决方案: 
                A:同步代码块 
                        synchronized(锁对象) 
                        { 
                                被同步的代码 
                        } 
                B:同步方法 
                        把synchronized加在方法上。 
 
        一般推荐使用同步代码块。代码自己写一遍,然后粘贴到下面: 
 
<<<同步代码块的锁对象是什么? 
 *                 同步代码块的锁是任意对象。  
 *  
 * 同步方法:就是把锁加在方法上 
 *                 格式:在方法上加synchronized关键字 
 *  
 *                 同步方法的锁对象是谁? this对象 
 *  
 * 静态方法的锁对象是谁呢? 
 *                 是当前类的字节码文件对象。 
 *                         类名.class        -        Class类型的对象 
 *  
 * 以后我们用同步代码块还是同步方法呢? 
 *                 被同步的内容越少越好,所以,一般使用同步代码块。                 
 *                 如果一个方法内部全部都被同步了,那么,可以考虑使用同步方法。>>> 
public class TicketRunnable implements Runnable{ 
 
        private static int tickets = 100; 
        private Object obj = new Object(); 
        private Demo d = new Demo(); 
         
        @Override 
        public void run(){ 
                int x = 0; 
                while(true){ 
                        if(x%2 == 0){        //加这条语句就是为了展示两种线程安全结局方案 
                                synchronized(this){        //因为方法上的锁对象是this. 
                                        if(tickets>0){ 
                                                Thread.sleep(100);        //这句必须try...catch... 
                                                System.out.println(Thread.currentThread()+"---"+tickets--); 
                                        } 
                                } 
 
                        }else{ 
                                check();//该方法用的是在方法上加synchronized; 
                        } 
 
                }         
 
        } 
 
} 
 
.............................. 
(7)线程间的通信问题 
                学生类: 
                设置学生属性的类: 
                获取学生属性的类: 
                测试类: 
 
 
 面试题:sleep和wait()的区别? 
         wait():是Object类的方法,可以不用传递参数。释放锁对象。 
         sleep():是Thread类的静态方法,需要传递参数。**不释放锁对象。 
 
 
public class SetStudent2 implements Runnable { 
 
public class GetStudent2 implements Runnable { 
 
public class Student2 { 
 
public synchronized void set(Student2 s){ 
                if (s.flag) { 
                        try { 
                                this.wait(100); 
                        } catch (InterruptedException e) { 
                                // TODO Auto-generated catch block 
                                e.printStackTrace(); 
                        } 
                } 
                this.name = s.name; 
                this.age = s.age; 
                 
//原因不在这,这里s从头到尾只有一个对象,所以用this和s是一样的。 
//s.flag=true;        s.notify(); 
                this.flag = true; 
                this.notify(); 
        } 
        public synchronized void get(Student2 s){ 
                if (!this.flag) { 
                        try { 
                                this.wait(100); 
                        } catch (InterruptedException e) { 
                                // TODO Auto-generated catch block 
                                e.printStackTrace(); 
                        } 
                } 
                System.out.println(s.name+"---"+s.age); 
                this.flag = false; 
                this.notify(); 
        } 
 
} 
 
(8)常见的方法 
                优先级 
                暂停线程 
                加入线程 
                守护线程 
 
main方法本身就是一个线程。 
 *public final void setDaemon(boolean on):设置线程为守护线程,一旦前台(主线程),结束,守护线程就结束了。 
DaemonDemo dd = new DaemonDemo(); 
Thread t1 = new Thread(dd); 
t1.setDaemon(true); 
 
public final void join():等待该线程终止。  
 * 一旦有join()线程,那么,当前线程必须等待,直到该线程结束。 
JoinDemo pd = new JoinDemo(); 
Thread t1 = new Thread(pd); 
t1.setName("林平之"); 
t1.join();                //需要处理异常 
 
测试线程的优先级问题: 
 *                 线程默认优先级是5。范围是1-10。 
 * public final int getPriority():获取线程优先级 
 * public final void setPriority(int newPriority):更改线程的优先级。  
 * 注意:优先级可以在一定的程度上,让线程获较多的执行机会。 
PriorityDemo pd = new PriorityDemo(); 
Thread t1 = new Thread(pd); 
t1.setName("林平之"); 
t1.setPriority(10); 
 
 public static void yield():暂停当前正在执行的线程对象,并执行其他线程。 
Thread.yield();                //在线程run()方法里使用。 
 
 
(9)面试题: 
                sleep()和wait()的区别? 
                启动线程到底调用的是哪个方法? 
 
                run()和start()的区别? 
                同步的原理,以及有几种实现方式? 
 
 
多线程记住这几个代码就好: 
**4个窗口买100张票 数据无误 
**学生类设置、获取信息交替 
 
 
 |