线程

进程

一个程序的运行状态和资源占用的描述
进城是程序的一个动态过程,指的是从代码加载到执行完毕的一个完成过程

特点:独立性,动态性,并发性
1)每个进程都有一个主线程
2)一个进程可以创建若干个线程
3)各个线程抢占进程的资源(CPU 内存)
4)进程之间不共享资源,相互独立

多线程

早期的操作系统都是单进程,如DOS操作系统,同一时间只能操作一件事情.
iOS也是单进程

多进程:在操作系统中能(同时)运行多个任务(程序)
(CPU飞速切换,看起来像在同时做的)

多线程:在同一应用程序中有多个顺序流(同时)执行

一个程序一个进程,下有多个线程

线程的执行过程
创建线程的方法:
1.定义一个线程类,继承类Thread并重写其中的方法run();.方法run()称为线程体.

public class ThreadT extends Thread {
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("ThreadT--->" + i);
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        ThreadT tf = new ThreadT();
        tf.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("main--->" + i);
        }
    }
}

2.提供一个实现接口Runnable的类作为县城的目标对象,在初始化一个Thread类或Thread子类的线程对象时,把目标对象传递给这个线程实例,由该目标对象提供线程体。

public class ThreadT2 implements Runnable {
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("run--" + i);
        }
    }
}

public class ThreadTest2 {
    public static void main(String[] args) {
        ThreadT2 t2 = new ThreadT2();//生成一个Runnable接口实现类的对象
        Thread tr = new Thread(t2);//生成一个Thead对象,并将Runnable接口实现类的对象作为参数传给该Thread对象
        tr.start();//通知Thread对象执行start方法
        for (int i = 0; i < 20; i++) {
            System.out.println("main---" + i);
        }
    }
}

现成的简单控制方法

中断线程:
1)Thread.sleep(time);//当前线程休眠一段时间,休眠结束后就绪继续抢cpu,抢到了才执行

public class ThreadT2 implements Runnable {
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("run--" + i);
            if(i==10){
                try{
                Thread.sleep(2000);
                }catch(Exception e){
                    System.out.println(e);
                }
            }
        }
    }
}

2)Thread.yield();//当前线程让出cpu,再抢cpu(???)

设置线程的优先级
3)getPriority();得到线程优先级
4)setPriority();设置线程的优先级

public class ThreadTest2 {
    public static void main(String[] args) {
        ThreadT2 t2 = new ThreadT2();
        Thread tr = new Thread(t2);
        tr.setPriority(Thread.MAX_PRIORITY);//设置线程的优先级 MAX_PRIORITY,MIN_PRIORITY
        tr.start();
        System.out.println(tr.getPriority());//得到线程优先级
    }
}

5)Thread.join();//合并线程

多线程数据安全

线程同步错误:多线程共用同一份数据时会发生.

public class MyThread implements Runnable{
    int i = 100;
    public void run(){
        while(true){
            //同步代码块
            synchronized(this){//同步锁 
            //另一个线程即使抢占cpu也需要等待拿到同步锁的线程完成代码块内的内容并释放同步锁
                //Thread.currentThread()返回一个当前正在执行这段代码的线程的引用
                System.out.println(Thread.currentThread().getName() + i);
                i--;
                Thread.yield();
                if(i<0){
                    break;
                }
            }
        }
    }
}

public class Test{
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        //生成两个Thread对象,但是这两个对象共用同一个线程体
        Thread t1 = new Thread(myThread);
        Thread t2 = new Thread(myThread);
        t1.setName("线程a");
        t2.setName("线程b");
        t1.start();
        t2.start();
    }
}

synchronized关键字

同步锁锁住的不是代码块,是指定的对象
一旦一个线程获得了一个对象的同步锁,那么这个对象上面的所有其他的同步的代码都无法被其他线程执行,同步锁被释放之后才能执行
同步代码块可以明确的指出锁定的对象.

同步方法:

public synchronized void fun(){

}

同步方法锁住的是this,即调用这个方法的对象.

public class Service implements Runnable{
    public void fun1(){
        synchronized(this){
            try{
                Thread.sleep(1000*3)
            }catch(Exception e){
                System.out.println(e);
            }
            System.out.println("fun1");
        }
    }
    public void fun2(){
        synchronized(this){
            System.out.println("fun2");
        }
    }
}

public class MyThread1 implements Runnable{
    private Service service;
    public MyThread1(Service service){
        this.service = service;
    }
    public void run(){
        service.fun1();
    }
}

public class MyThread2 implements Runnable{
    private Service service;
    public MyThread2(Service service){
        this.service = service;
    }
    public void run(){
        service.fun2();
    }
}

public class Test{
    public static void main(String[] args){
        Service service = new Service();
        Thread t1 = new Thread(new MyThread1(Service));
        Thread t2 = new Thread(new MyThread2(Service));
        t1.start();
        t2.start();
    }
}

线程之间的通信

典型案例:生产者 消费者模式

wait();//线程停止执行,释放锁,在锁外边处于等待状态.是Object的方法.必须放在同步代码块中使用.
sleep();//Thread类的方法,指定休眠时间结束后线程自动进入就绪状态.休眠期间锁依然有效.可以在代码的任何位置使用
notify();//向其他等待的线程发出可执行通知,同时放弃锁
notifyAll();//