您的位置:首页 > 编程语言 > Java开发

java线程基础知识点总结

2018-12-16 20:33 344 查看

在提到java线程的时候,常常让会人想到了计算中的进程,两种有什么区别呢?在java中线程是怎么实现的呢?其又给我们提供了哪些好用的方法?怎么在程序中实现多线程呢?带着这些问题,自己在此对java中的线程基本知识点进行总结,便于日后学习
1)进程:一般来说进程就是指计算机中某段程序的执行过程,也可以说是某个程序的执行,在广义上来说,进程是指具有一定独立功能的程序关于某个数据集合的操作,是os中的基本分配和执行单位;
2)线程:通常一个进程包含多个线程,是进程中所含程序内部的顺序控制流,线程可以调用进程中所拥有的内存,cpu等资源,
而多线程是指在一个程序中,可以采用多个线程来对任务进行同时处理,进而提高资源的使用效率。
3)java中线程是通过java.lang.Thread类来实现的,通过创建Thread类的实例来创建新的线程,并通过调用Thread.strat()方法来启动线程;有两种实现方式

(1):直接继承Thread类,然后重写其中的run()方法;

(2):实现Runnable接口,然后实现run()方法;因为java中类的单继承的原因,实现Runnable()接口的方式可以为多个线程
提供共享数据。
class TestRun {
    public static void main(String [] args) {
        //继承Thread类,重新run()方法
        Test1 t1 = new Test1();
        t1.start();
        
        //实现Runnable接口,实现run()方法
        Test2 t2 = new Test2();
        Thread tt = new Thread(t2);
        tt.start();
    }
}
class Test1 extends Thread{
    @Override
    public void run(){}
}

class Test2 implements Runnalbe{
    public void run(){}

}

4)线程在os中存在以下三种状态:就绪状态;运行状态;阻塞状态;具体关系见图,注意当调用线程的start()方法后,实际该线程进入就绪状态,并不是立即进行运行状态;

5)线程的基本控制方法:
isAlive()--------判断线程是否终止;
getPriority()/setPriority()----获取线程的优先级/设置线程的优先级,在java中线程的优先级使用1-10来表示,缺省为5,数值越大,优先级越高,线程分配的cpu时间片越多,同时java中还定义一些常量Thread.MIN_PRIORITY = 1;Thread.MAX_PRIORITY = 10;Thread.NORM_PRIORITY = 5;
Thread.sleep(***) -------线程睡眠***毫秒数,此时让出cpu,让其他线程先执行一会,然后再进行就绪状态;其是Thread的静态方法下,需要抛出InterruptedException异常;
join()---------调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程执行结束,然后再执行当前线程;需要抛出InterruptedException异常;
yield() ------ 让出cpu,进入就绪队列等待调度;需要抛出InterruptedException异常;
wait()--------- 让当前线程进入对象的wait pool;需要抛出InterruptedException异常;
notify()/notifyAll() ----唤醒wait pool中的一个/所有等待的线程,需要抛出InterruptedException,且与wait()方法成对进行使用;

6)对于sleep方法,举例说明:
public class TestSleep{
    public satic void main(String[] args){
        RunTest rt = new RunTest();
        rt.start();
        
        for(int i=0; i<10; i++) {
            System.out.println("Main Thread:" + i);
        }
    }
}

class RunTest extends Thread{
    @Override
    public void run(){
        for(int i=0; i<10; i++) {
            try{
                Thread.sleep(5000);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("RunTest Thread:" + i);
        }
    }
}
在执行时,显示主线程执行,然后创建rt线程并启动,在线程rt没执行一次,然后休眠5秒,此时主线程在执行,依次类推;

7)线程同步:在实际程序运行过程中常常存在共享内存的情况,每个线程都可以对其共享中的数据进行修改和读取;但对于同一数据在同一时间段存在多个线程同时修改或者读取,则就可能产生“脏数据”的问题;为此,必须进行线程的同步,同步最简单的方式是对数据“加锁”,以保证该数据同一时间段仅有一个线程可以进行修改或者读取,从而避免了“脏数据”的产生,在java中使用synchronized关键字来实现数据同步;当某个对象使用synchronized修饰时,表明该对象在任意时刻只能有一个线程访问;
放在方法声明中public synchronized void test(){};/或者直接修饰对象synchronized(this);
8)在程序运行中,如果一个类中同时存在加锁的方法与不加锁的方法,且两个方法中都存在对相同成员变量的改变,则在加锁方法调用且睡眠过程中,主线程在调用不加锁的方法,且改变变量的数值时,加锁方法中的变量数据一起是发生改变,小例子如下:
public class TT implements Runnalbe{
    int b = 100;
    public synchronized void m1(){
        b =1000;
        try{
            Thread.sleep(5000);
        }catch(InterruptedException e){
            e.printStackTrace();
        }        
    }

    public void m2(){
        try{
            Thread.sleep(2500);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        b =2000;
    }
    public void run(){}
}

在调用m1()方法的过程中如果调用了m2()方法,此时m2()中对b的数值进行改变,则在返回m1()方法的过程中,b的数值会被改变掉;但是如果将该变量改完方法内的变量,那么就不存在上述问题,因为每个线程在执行的时候会把局部变量存放在各自栈帧的工作内存中(栈帧进入虚拟机栈),虚拟机栈线程间不共享,因此方法体内的变量都是线程安全的。

8)死锁:死锁是指多线程在执行过程中,因为资源竞争或者是彼此通信而造成的一种阻塞的现象,造成
程序一直处于等待状态!下面使用小列子进行说明:
public class TestDeadLock implements Runnable{
    public int flag =1;
    static Object o1 = new Object(), o2 =  new Object();
    public void run(){};    
    if(flag == 1) {
        synchronized(o1) {
            try{
                Thread.sleep(500);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            synchronized(o2) {
                System.out.println("1");< 20000 br />             }
        }
    }    
    if(flag == 0) {
        synchronized(o2) {
            try{
                Thread.sleep(500);
            }catch(InterruptedException e){
                e.printStackTrace();
            }         
            synchronized(o1) {
                System.out.println("0");            
            }
        }
    }
}

public static void main(String[] args) {
    TestDeadLock td1 = new TestDeadLock();
    TestDeadLock td2 = new TestDeadLock();
    td1.flag = 1;
    td2.flag = 0;
    Thread t1 = new Thread(td1);
    Thread t2 = new Thread(td2);
    t1.start();
    t2.start();
}

在这例子中存在两种情况,而这两种情况,都需要等待对方的资源,因此存在死锁的问题;

9)对于wait()与notify()/notifyAll()方法,使用“生产者与消费者”的例子进行说明:

public class ProducerConsumer {
    public static void main(String[] args) {
        SynPool sp = new SynPool();
        Producer pc = new Producer(sp);
        Consumer cr = new Consumer(sp);
        new Thread(pc).start();
        new Thread(cr).start();
    }
}

class Manto {
    int id;
    Manto(int id){
        this.id = id;
    }

    @Override
    public String toString() {
        return "mantou is:" + id;
    }
}

class SynPool{
    int index = 0;

    Manto[] arrMT = new Manto[6];

    public synchronized void push(Manto mt){
        while(index == arrMT.length){
            try {
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }

        }
        this.notify();
        arrMT[index] = mt;
        index ++;

    }

    public synchronized Manto pop(){
        while(index == 0){
            try{
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }

        }
        this.notify();
        index --;
        return arrMT[index];
    }
}

class Producer implements Runnable{
    SynPool sp = null;
    Producer(SynPool sp){
        this.sp = sp;
    }

    public void run(){
        for(int i=0; i<20; i++){
            Manto each = new Manto(i);
            sp.push(each);
            System.out.println("生产了:"+ each);
            try{
                Thread.sleep(2000);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

class Consumer implements Runnable{
    SynPool sp = null;
    Consumer(SynPool sp){
        this.sp = sp;
    }

    public void run(){
        for(int i=0; i<20; i++){
            sp.pop();
            System.out.println("消费了:"+ sp.pop());

            try{
                Thread.sleep(2000);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}


 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: