黑马程序员——多线程

——- android培训java培训、期待与您交流! ———-
进程:一个应用程序,在运行的时候,所占有内存的空间区域,这个程序的进程
线程:就是你的程序,对于CPU的一条执行的道路
线程依赖于进程,进程依赖于线程吗
一个正在执行的程序,没有活动的线程,没有一个执行路径,这个进程自动结束

线程和进程都是由操作系统来创建,
我们实现多线程程序,依靠JVM帮你完成
线程也是一种对象,线程对象的描述类 java.lang.Thread
操作线程必须依赖Thread类

第一种创建线程方式

定义类,继承Thread类,定义类也就变成了线程类
该类,重写Thread类run方法
创建子类对象
调用Thread类的方法 start() 开启线程

public class SubThread extends Thread{
    public void run(){
        for(int x = 0 ; x<100 ; x++){
            System.out.println("run..."+x);
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) {

        SubThread s = new SubThread();
        s.start();
        s.start();
        for(int x = 0 ; x < 100 ; x++){
            System.out.println("main..."+x);
        }
    }
}

为什么重写run方法
线程是一条执行的路径,路径运行的是什么代码,Sun公司不清楚
无论你要运行什么代码,全部放run中

CPU对于线程调度问题
CPU在某一时刻 一段时间之内,执行一条指令
线程得到CPU的时间片,CPU将这个段时间交给一个线程执行

第二种创建线程的方式

定义类,实现Runnable接口
重写接口中的抽象方法 run()
创建Thread类对象。Thread构造方法中,传递Runnable接口的实现类对象
调用Thread类start方法

线程中的同步原理
代码块
synchronized(任意对象){
线程操作的共享数据
}

//定义类,实现Runnable接口,重写run方法
class TicketRunnable implements Runnable{
    private int tickets = 100;
    private Object obj = new Object();
    public void run(){
        while(true){
         synchronized(obj){ 
            if(tickets>0){
                try{Thread.sleep(10);}catch(Exception e){}
                System.out.println(Thread.currentThread().getName()+"出售第"+tickets--);
            }
         }
        }
    }
}

public class ThreadDemo8 {
    public static void main(String[] args) {
        //创建Thread类对象,传递Runnable接口的实现类的对象
        TicketRunnable t = new TicketRunnable();
        Thread t0 = new Thread(t);
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);

        t0.start();
        t1.start();
        t2.start();
    }
}

对象:对象监视器,对象锁, 锁
线程运行,前面是一个同步代码块的时候,
判断同步中的所有还有没有,如果有这个锁,就获取到这个锁 进入同步中的
如果后还有其他线程,也在同步代码块外面的时候,其他线程也会判断有没有这个锁,
锁已经被上一个线程拿走,没有锁的线程,等在同步外面。
等待在同步中线程,出去后,把锁归还同步代码块

多线程操作同一个数据的时候,出现安全隐患
单线程,没有安全隐患

使用匿名内部类,实现多线程程序

public class ThreadDemo {
    public static void main(String[] args) {
        new Thread(new Runnable(){
            public void run(){
                for(int x = 0 ; x < 10 ;x++){
                    System.out.println(Thread.currentThread().getName()+"run.."+x);
                }
            }
        }).start();

        new Thread(){
            public void run(){
                for(int x = 0 ; x < 10 ;x++){
                    System.out.println(Thread.currentThread().getName()+"run.."+x);
                }
            }
        }.start();

    }
}

第三种实现线程的方式, JDK5以后

继承Thread类
实现Runnable即可
实现Callable接口 – 线程池支持,Thread类不支持

线程池出现JDK1.5级以后版本
java.util.concurrent

Executors 工厂类 FactoryClass
创建对象,线程池
三个静态方法
static ExecutorService newCachedThreadPool() 创建新的线程池对象
static ExecutorService newFixedThreadPool(int nThreads) 创建新的线程池对象,参数指定线程个数
static ExecutorService newSingleThreadExecutor() 创建新的线程池对象,线程个数1个

ExecutorService 接口 用来管理线程池

接口方法
Future submit(Callable task) 运行线程池中的线程 ,传递Callable接口实现类对象
Future

public class CallablePool implements Callable<String>{
    public String call() {
        return "实现线程第三种方式";
    }
}
/*
 * 创建线程池,让线程运行线程
 * 实现步骤:
 *   Executors类,静态方法 newFixedThreadPool(int nThreads)
 *   创建线程池 2个线程
 *   返回线程池管理对象ExecutorService
 *   线程池管理对象ExecutorService,方法submint运行线程
 *   submit(Runnable接口实现类)
 *   
 *   ExecutorService 接口方法shutdown
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(2);
        es.submit(new RunnablePool());
        es.submit(new RunnablePool());

        es.shutdown();

    }
}

同步代码块的相互嵌套中,多线程争夺同一个锁对象,产生程序的假死现象,多线程中的死锁

class DeadLock implements Runnable{
    //定义成员变量,将控制线程,先进入A,还是先进入B
    private boolean flag ;
    DeadLock(boolean flag){this.flag=flag;}
    public void run(){
        while(true){
            //判断flag的是,如果是真,先进A,后进B
            if(flag){
                //同步的嵌套
                synchronized(ALock.alock){
                    System.out.println("if...A");
                    //进入到B锁
                    synchronized(BLock.block){
                        System.out.println("if...B");
                    }
                }
            }else{
                //如果Flag值的是假,先进B,在进A
                synchronized(BLock.block){
                    System.out.println("else...B");
                    //进入到、A
                    synchronized(ALock.alock){
                        System.out.println("else...A");
                    }
                }
            }
        }
    }
}

public class DeadLockThreadDemo {
    public static void main(String[] args) {
        DeadLock d1 = new DeadLock(true);
        DeadLock d2 = new DeadLock(false);
        Thread t1 = new Thread(d1);
        Thread t2 = new Thread(d2);

        t1.start();
        t2.start();
    }
}


/*
 * 定义两个对象锁,A,B
 * 唯一性的 
 */
class ALock{
    public static final ALock alock = new ALock();
}
class BLock{

    public static final BLock block = new BLock();
}

1.多线程操作的方法中、等待wait和唤醒方法notify为什么没有出现在Thread类中,而出现在了Object类中?
保证线程数据安全,使用同步锁,锁对象是任意对象,方法等待与唤醒必须有锁的支持,
方法必须定义在Object类中,JAVA中的所有对象均以有此方法

2.线程操作方法中,sleep 和 wait 有什么区别
sleep方法是Thread类的静态方法
wait方法是Object类的非静态方法

sleep方法,到时间自己醒来,继续执行 ,
wait方法,等待其他线程唤醒后才执行 ,

sleep 不会释放锁
wait 释放锁,被唤醒后,从新获取锁,才执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值