java学习笔记6(线程)

  线程就是进程的儿子,没有了进程线程也( •̀ ω •́ )y就没有了,javascript没有线程的概念,但是有定时器(setTimeout),虽然没有java中名副其实的线程,但是也够用了;

  java要使用线程有两种方式, 第一种是直接让类继承Thread, 第二种是让类继承Runnable接口的方式, 推荐使用继承接口(Runable)的方式使用线程;

  第一种方式,使用extends继承Thread:

运行下面代码

复制代码
public class ThreadDemo0 extends Thread{
    private String name;
    public /*void*/ ThreadDemo0(String name) {
        this.name = name;
    };
    public void run() {
        for(int i=0; i<10; i++) {
            System.out.println("THREAD: "+name+" run in thread " + i);
        };
    };

    public static void main (String args[]) {
        /*
        new ThreadDemo0("hehe").run();
        new ThreadDemo0("lala").run();
        */
        new ThreadDemo0("hehe").start();
        new ThreadDemo0("lala").start();
    };
};
复制代码

  这种方式继承好理解, 要注意的是如果new出的线程 new ThreadDemo0("hehe") , start一次以后,再start一次是会报异常的,

  所以我们每一次都要重新new这个类, 每一次都产生了新实例, 新实例跟上次实例化的实例一点关系都没有,我们无法简单地通过多线程同时做一件事情;

运行下面代码

复制代码
public class ThreadDemo0 extends Thread{
    private String name;
    private int arr[];
    public /*void*/ ThreadDemo0(String name) {
        this.name = name;
    }
    public void setArr (int arr[]) {
        this.arr = arr;
    }
    public void run() {
        for(int i=0; i<this.arr[0]; i++) {
            System.out.println("THREAD: "+name+" run in thread " + i);
        };
    };

    public static void main (String args[]) {
        int sArr[] = {10};
        ThreadDemo0 t0 = new ThreadDemo0("hehe");
        ThreadDemo0 t1 = new ThreadDemo0("lala");
        t1.setArr(sArr);
        t0.setArr(sArr);
        t1.start();
        t0.start();
    };
};
复制代码

 

  Runnable跟Thread有点不同, Runnable相当于你运行的代码在多个线程里面是共享的, 这个才是真正的多线程哇

运行下面代码

复制代码
public class RunAndThread0 implements Runnable{
    private int ticket = 5;
    public RunAndThread0( ) {
    }
    public void run() {
        while( true ) {
            if( ticket>0 ) {
                System.out.println("sell one; has tickets " + --ticket);
            }else{
                return ;
            }
        }
    }
    public static void main(String []args) {
        RunAndThread0 run = new RunAndThread0();
        //to use interface Runnable to share the variables;
        new Thread(run).start();
        new Thread(run).start();
    }
}
复制代码

  Runnable是实现的Thread的run接口, 最后再通过Thread启动线程;

  如果你不想共享作用域内的代码变量,你再重新实例化一个Runnable,重启一个线程, 这个效果跟extends Thread一样的:

运行下面代码

复制代码
public class RunnableDemo0 implements Runnable {
    private String name;
    public RunnableDemo0(String name) {
        this.name = name;
    }
    public void run() {
        for(int i=0; i<10; i++) {
            System.out.println(name+" in thread " + i);
        }
    }
    public static void main(String[] args) {
        RunnableDemo0 hehe = new RunnableDemo0("hehe");
        Thread tHehe = new Thread(hehe);
        RunnableDemo0 lala = new RunnableDemo0("lala");
        Thread tLala = new Thread(lala);
        
        tHehe.start();
        tLala.start();
    }
}
复制代码

  

  通过Thread.currentThread()可以获取当前的正在执行的线程, getName()可以获取线程的名字, 如果我们没有给线程起名字, 系统会为线程起名字,像这样的:

  Thread-0, Thread-1, Thread-2, Thread-3....

运行下面代码

复制代码
public class CurrentThread implements Runnable{
    public void run( ) {
        System.out.println( Thread.currentThread().getName() );
    }
    public static void main(String []args) {
        CurrentThread  ct = new CurrentThread();
        Thread tCt = new Thread(ct);
        tCt.start();
        System.out.println(tCt.isAlive());
        //this is main thread;
        new CurrentThread().run();

        System.out.println(tCt.isAlive());
        System.out.println(tCt.isAlive());
        System.out.println(tCt.isAlive());
    }
}
复制代码

 

  Thread.sleep,就是让线程睡觉去, 参数是毫秒, (1000毫秒为1秒),Thread.sleep要用tryCatch包裹起来,要么编译的时候会有提示,你不加,他还编译不过去(太矫情了,这个是为什么呢?):

运行下面代码

复制代码
public class ThreadSleep implements Runnable{
    public void run() {
        try{
            Thread.sleep(5000);
        }catch(Exception e) {
            e.printStackTrace();
        }
        System.out.println("sleeping");
    }
    public static void main(String []args) {
        new Thread( new ThreadSleep() ).start();
    }
}
复制代码

 

  线程的优先级Priority, 优先级越高的话, 线程越早开始跑,系统默认的优先级为5, 最低的为1, 最高的为10,通过setPriority设置到线程的实例:

运行下面代码

复制代码
public class ThreadPriority implements Runnable {
    public void run( ) {
        for( int i=0 ;i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + Thread.currentThread().getPriority());
        };
    }
    public static void main(String args[]) {
        new Thread(new ThreadPriority()).start();
        Thread t0 = new Thread(new ThreadPriority());
        t0.setPriority(10);
        t0.start();
        Thread t1 = new Thread(new ThreadPriority());
        t1.setPriority(1);
        t1.start();
    }
}
复制代码

 

  线程的join方法, 就是把一个线程加在另一个线程后面运行的(排队上车, 你先上好了,我等等, 我就跟你后面):

运行下面代码

复制代码
public class ThreadJoin implements Runnable{
    private Thread t;
    public ThreadJoin() {}
    public ThreadJoin( Thread t ) {
        this.t = t;
    }
    public void run() {

        for(int i=0 ; i<40; i++) {
            try{
                if(i>10&&t.isAlive()) {
                    t.join();
                };
            }catch( Exception e){
                //e.printStackTrace();        
            }
            System.out.println( "thread name"+ Thread.currentThread().getName() + " i = " + i );
        }
    }
    public static void main(String [] args) {
        Thread t0 = new Thread(new ThreadJoin());
        t0.start();
        Thread t1 = new Thread(new ThreadJoin(t0));
        t1.start();

    }
}
复制代码

 

  如果一个线程同时操作一条数据,因为两个线程不是同步的,导致数据不同步, 就比如两个人抢银行, 一个人抢了30元, 一个人抢了40元,本来银行就只有40元钱, 银行跟两个盗窃者承诺了给钱 ,银行给了一个人40元, 又给了一个人30元, 发现自己亏了30元, 银行郁闷了:

运行下面代码

复制代码
public class ThreadSync implements Runnable{
    private int ticket = 10;
    public void run( ) {
        while(true) {
            if(ticket>0) {
                try{
                    //we should to do someting , to sure users state;
                    Thread.sleep(1000);
                }catch( Exception e) {
                    e.printStackTrace();
                };

                ticket--;
                System.out.println("lev :" + ticket);
            }else{
                return;
            }
        }
    }
    public static void main(String [] args) {
        ThreadSync ts = new ThreadSync();
        Thread t0 = new Thread(ts);
        Thread t1 = new Thread(ts);
        Thread t2 = new Thread(ts);
        Thread t3 = new Thread(ts);
        t0.start();
        t1.start();
        t2.start();
        t3.start();
    }
}
复制代码

  卖出去的票出问题, 坑爹地变成了负数, 然道让多出来的乘客站着吗。。。。多线程的问题

  如何解决这个问题呢,我们使用synchronized方法:

运行下面代码

复制代码
public class Sync implements Runnable{
    private int ticket = 10;
    public void run( ) {
        while(true) {
            synchronized( this ) {
                if(ticket>0) {
                    try{
                        //we should to do someting , to sure users state;
                        Thread.sleep(1000);
                    }catch( Exception e) {
                        e.printStackTrace();
                    };
                    ticket--;
                    System.out.println("lev :" + ticket);
                }else{
                    return;
                }
            }
        }
    }
    public static void main(String [] args) {
        Sync ts = new Sync();
        Thread t0 = new Thread(ts);
        Thread t1 = new Thread(ts);
        Thread t2 = new Thread(ts);
        Thread t3 = new Thread(ts);
        t0.start();
        t1.start();
        t2.start();
        t3.start();
    }
}
复制代码

 

 

  或者使用synchronzed方法语句:

运行下面代码

复制代码
public class SyncB implements Runnable{
    private int ticket = 10;
    public void run( ) {
        while(true) {
            if( toRun() ) {
                return ;
            }
        }
    }
    public synchronized boolean toRun( ) {
        if(ticket>0) {
            try{
                //we should to do someting , to sure users state;
                Thread.sleep(1000);
            }catch( Exception e) {
                e.printStackTrace();
            };
            ticket--;
            System.out.println("lev :" + ticket);
            return false;
        }else{
            return true;
        }
    }
    public static void main(String [] args) {
        Sync ts = new Sync();
        Thread t0 = new Thread(ts);
        Thread t1 = new Thread(ts);
        Thread t2 = new Thread(ts);
        Thread t3 = new Thread(ts);
        t0.start();
        t1.start();
        t2.start();
        t3.start();
    }
}
复制代码

  运行后的效果跟上面一模一样,就可以避免线程同时访问导致数据不对头的问题;

本文作者:方方和圆圆

本文链接:https://www.cnblogs.com/diligenceday/p/4339946.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   方方和圆圆  阅读(166)  评论(0编辑  收藏  举报

再过一百年, 我会在哪里?

💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
点击右上角即可分享
微信分享提示