java基础 我的线程初次学习

线程的基本概念:

    线程是一个程序内部顺序控制流

线程与进程的区别:

  • 每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较开销
  • 线程可以看成轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小
  • 多进程:在操作系统中能同时运行多个任务(程序)
  • 多线程:在同意应用程序中有多个顺序流同时执行

 

Java的线程是通过java.lang.Tread类来实现的

 

VM(Java虚拟机)启动时会有一个由主方法(public static void main(){})所定义的线程。

 

可以通过创建Tread的实例来创建新的线程。

每个线程都是通过某个特定Tread对象所对应的方法run()来完成其操作的,方法run()成为线程体

通过调用Thead类的start()方法启动一个线程

 

 

 

线程的创建和启动

    有两种方式创建新的线程。

    第一种:

  • 定义线程类实现Runnable接口
  • Thread myTread = new Thread(target)  //target为Runnable接口类型.
  • Runnable中只有一个方法:public void run();//用以定义线程运行体
  • 使用Runnable接口可以为多个线程提供共享的数据。
  • 在实现Runnable接口的类的run方法定义中可以使用Tread的静态方法:public static Thread currentThread()获取当前线程的引用。

public class TestThread1{

    public static void main(String[] args){

        Runner1 r = new Runner1();

        Thread m = new Thread(r);

        m.start();

        for(int i=1;i<=100;i++){

            System.out.println("MainThread i: "+i);

        }

    }

}

 

class Runner1 implements Runnable{

    public void run()

    {

        for(int i=1;i<=100;i++){

            System.out.println("Runner1 i: "+i);

        }

    }

}

 

 

第二种:

  • 可以定义一个Thread的子类并重写其run方法如:

class MyThread extends Thread{

    public void run()

    }

 }

  • 然后生成该类的对象:
    • MyThread myThread=new MyTread(...)

public class TestThread1{

    public static void main(String[] args){

        Runner1 r = new Runner1();

        //Thread m = new Thread(r);

        r.start();

        for(int i=1;i<=100;i++){

            System.out.println("MainThread i: "+i);

        }

    }

}

 

class Runner1 extends Thread{

    public void run()

    {

        for(int i=1;i<=100;i++){

            System.out.println("Runner1 i: "+i);

        }

    }

}

 

注意:尽量能使用implements Runnable接口就尽量使用接口


 

线程状态:

线程控制基本方法

方法

功能
isAlive()判断线程是否还“活着”,即线程是否还未终止。
getPriority()获得线程的优先级数值。
setPriority()设置线程的优先级数值。
Thread.sleep()将当前线程睡眠指定毫秒数。
join()调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行。
yield()让出CPU,当前线程进入就绪队列等待调度。
wait()当前线程进入对象的wait pool

notify()/

notifyAll()

唤醒对象的wait pool中的一个/所有等待线程

 

sleep方法:

  •     可以调用Thread的静态方法:
    •  public static void sleep(long millis) throws InterruptedException(使得当前线程休眠,暂时停止执行millis毫秒)
  • 由于是静态方法,sleep可以由类名直接调用:Thread.sleep()

//每隔一秒钟打印时间,主函数睡眠10秒后打断run1这个类使得它停止

import java.util.*; //调用Date()

public class TestInterrupt{

    public static void main(String []args){

        run1 r = new run1();

        r.start();

        try{

            Thread.sleep(10000);

        }catch(InterruptedException e){}

        r.interrupt();

    }

}

class run1 extends Thread{

    public void run(){

        while(true){

            System.out.println("---"+new Date()+"---");

            try{

                sleep(1000);

            }catch(InterruptedException e){

                return;

            }

        }

    }

}

 


join方法:

  • 合并某个线程

 

public class TestJoin{

    public static void main(String[] args){

        MyThread2 t2 = new MyThread2("t2");

        t2.start();

        try{

            t2.join();            //会先执行完t2,才会执行下面的代码

        }catch(InterruptedException e){return;}

        for(int i = 0;i<=10;i++){

            System.out.println("Main: "+i);

        }

    }

}

class MyThread2 extends Thread{

    MyThread2(String s){

        super(s);

    }

    public void run(){

        for(int i = 0;i<=10;i++){

            try{

                sleep(1000);

            }catch(InterruptedException e){return;}

            

        System.out.println(getName()+" :"+i);

        }

    }

}

 


yield方法

  • 让出CPU给其他线程执行的机会

public class TestYield{

    public static void main(String[] args){

        MyThread3 t1 = new MyThread3("t1");

        MyThread3 t2 = new MyThread3("t2");

        t1.start();

        t2.start();

    }

}

class MyThread3 extends Thread{

    MyThread3(String s){

        super(s);

    }

    public void run(){

        for(int i=0;i<100;i++){

            System.out.println(getName()+": "+i);

            if(i%10==0){

                yield();        暂时让其他线程执行多一些

            }

        }

    }

}

 


线程的优先级:

  • 线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级是5.
    • Thread.MIN_PRIORITY=1
    • Thread.MAX_PRIORITY=10
    • Thread.NORM_PRIORITY=5
  • 使用下述线程的方法获得或设置线程对象的优先级。
    • int getPriority();
    • void setPriority(int newPriority);

public class TestPriority{

    public static void main(String[] args){

        T1 t1 = new T1();

        T2 t2 = new T2();

        Thread tt1  = new Thread(t1);

        Thread tt2  = new Thread(t2);

        tt1.setPriority(Thread.NORM_PRIORITY +3);

        tt1.start();

        tt2.start();

    }

}

class T1 implements Runnable{

    public void run(){

        for(int i=0;i<1000;i++){

            System.out.println("T1: "+i);

        }

    }

}

class T2 implements Runnable{

    public void run(){

        for(int i=0;i<1000;i++){

            System.out.println("----T2: "+i);

        }

    }

}

 


 

正确的停止线程的方法:

public class TestThread4{

    public static void main(String[] args){

        Runner3 r = new Runner3();

        Thread t = new Thread(r);

        t.start();

        for(int i=0;i<100;i++){

            System.out.println("in thread main i="+i);

        }

        System.out.println("Thread main is over");

        r.shutDown();

    }

}

class Runner3 implements Runnable{

    private boolean flag = true;

    

    public void run(){

        int i=0;

        while(flag==true){

            i++;

            System.out.println(" "+i);

        }

    }

    public void shutDown(){

        flag=false;

    }

}

 


线程同步:

当某个对象被synchronized修饰时,表明该对象在任一时刻只能由一个线程访问(通俗来讲,该这里被锁住了)

public class TestSync implements Runnable{

    Timer timer = new Timer();

    public static void main(String[] args){

        TestSync test = new Thread(test);

        Thread t1 = new Thread(test);

        Thread t2 = new Thread(test);

        t1.start();

        t2.start();

    }

    public void run(){

        timer.add(Thread.currentThread().getName());

    }

}

class Timer{

    private static int num=0;

    public void add(String name){

      锁的第一种写法:  synchronized (this){

            num++;

            try{Thread.sleep(1);}

            catch(InterruptedException e){}

            System.out.println(name+", 你是第"+num+"个使用timer的线程");

        }

    }

}

class Timer{

    private static int num=0;

   锁的第二种写法: public  synchronized void add(String name){

            num++;

            try{Thread.sleep(1);}

            catch(InterruptedException e){}

            System.out.println(name+", 你是第"+num+"个使用timer的线程");

    }

}

如果高亮的地方被注释,也就是没有加锁,输出结果是两个 :你是第2个使用timer的线程

否则被锁住才会输出:你是1个使用timer的线程\n 你是第2个使用timer的线程

 

注意:死锁(互斥锁)

public class TestDeadLock implements Runnable{

    public int flag=1;

    static Object o1 =new Object(),o2 = new Object();

    public void run(){

        System.out.println("flag="+flag);

        if(flag==1){

            synchronized(o1){

                try{

                    Thread.sleep(500);

                }catch(Exception e){

                    e.printStackTrace();

                }

            }

            synchronized(o2){

                System.out.println("1");

            }

        }

        if(flag==0){

            synchronized(o2){

                try{

                    Thread.sleep(500);

                }catch(Exception e){

                    e.printStackTrace();

                }

            }

            synchronized(o1){

                System.out.println("0");

            }

        }

    }

}

一些问题:

提问:打印的结果是多少

public class TT implements Runnable{

    int b =100;

    

    public synchronized void m1() throws Exception{

        b=1000;

        Thread.sleep(5000);

        System.out.println("b= "+b);

    }

    

    public void m2(){

        System.out.println(b);

    }

    public void run(){

        try{

            m1();

        }    catch(Exception e){

            e.printStackTrace();

        }

    }

    public static void main(String[] args) throws Exception{

        TT tt = new TT();

        Thread t = new Thread(tt);

        t.start();

        Thread.sleep(1000);

        tt.m2();

        

        System.out.println(tt.b);

    }

}

结果:1000\n  1000

 

public class TT implements Runnable{

    int b =100;

    

    public synchronized void m1() throws Exception{  //只是保证只有一个线程使用这个方法,其他的方法依然可以使用

        b=1000;

        Thread.sleep(5000);

        System.out.println("b= "+b);

    }

    

    public void m2()throws Exception{

        Thread.sleep(2500);

        b=2000;

    }

    public void run(){

        try{

            m1();

        }    catch(Exception e){

            e.printStackTrace();

        }

    }

    public static void main(String[] args) throws Exception{

        TT tt = new TT();

        Thread t = new Thread(tt);

        t.start();

        tt.m2();

        

    }

}

结果:2000 

public class TT implements Runnable{

    int b =100;

    

    public synchronized void m1() throws Exception{

        b=1000;

        Thread.sleep(5000);

        System.out.println("b= "+b);

    }

    

    public synchronized void m2()throws Exception{

        Thread.sleep(2500);

        b=2000;

    }

    public void run(){

        try{

            m1();

        }    catch(Exception e){

            e.printStackTrace();

        }

    }

    public static void main(String[] args) throws Exception{

        TT tt = new TT();

        Thread t = new Thread(tt);

        t.start();

        tt.m2();

        System.out.println(tt.b);

        

    }

}

结果 :1000/n b=1000

 


notify不能叫醒自己!!!

经典生产包子 消费包子同时进行的问题。考察到了wait(),notify(),sychronized等语法

//一个线程生产包子,一个线程消费包子

//注意栈的用到

public class ProducerConsumer{

    public static void main(String[] args){

        wtStack ww = new wtStack();

        producer p1 = new producer(ww);

        consumer c1 = new consumer(ww);

        Thread p = new Thread(p1);

        Thread c = new Thread(c1);

        p.start();

        c.start();

    }

}

class wotou{

    int id;

    wotou(int id){

        this.id=id;

    }

    public String toString(){

        return "wotou's id :"+id;

    }

}

class wtStack{

    int index=0;

    wotou[] wotous= new wotou[6];

    

    public synchronized void push(wotou ww){

        while(index==wotous.length){

            try{

                this.wait();          //使得当前的线程暂停

            }catch(InterruptedException e){

                e.printStackTrace();

            }

        }

        this.notify();               //唤醒一个其他的wait的线程 如果是notifyAll()则为唤醒其他所有的wait线程

        wotous[index]=ww;

        index++;

    }

    

    public synchronized wotou pop(){

        while(index==0){

            try{

                this.wait();

            }catch(InterruptedException e){

                e.printStackTrace();

            }

        }

        this.notify();

        index--;

        return wotous[index];

    }

}

class producer implements Runnable{

    wtStack ww = null;

    producer(wtStack ww){

        this.ww=ww;

    }

    public void run(){

        for(int i=0;i<20;i++){

            wotou temp = new wotou(i);

            System.out.println("生产了:"+temp);

            ww.push(temp);

            /*try{

                Thread.sleep((int)(Math.random()*20));

            }catch(InterruptedException e){

                e.printStackTrace();

            }

            */

        }

    }

}

class consumer implements Runnable{

    wtStack ww = null;

    consumer(wtStack ww){

        this.ww=ww;

    }

    public void run(){

        for(int i=0;i<20;i++){

            wotou temp = null;

            temp=ww.pop();

            System.out.println("消费了"+temp);

        }

        /*try{

                Thread.sleep((int)(Math.random()*20));

            }catch(InterruptedException e){

                e.printStackTrace();

            }

            */

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值