Java中Thread线程_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java中Thread线程

Java中Thread线程

 2018/10/25 12:18:54  andrew7676  程序员俱乐部  我要评论(0)
  • 摘要:1.实现线程的两种方式1.继承Thread类并重写run方法publicclassThreadTest{publicstaticvoidmain(String[]args){Thread1t1=newThread1("firstthread");Thread2t2=newThread2("secondthread");System.out.println(t1.getName());System.out.println(t2.getName());t1.start();t2.start();}
  • 标签:thread Java 线程
1. 实现线程的两种方式
class="java">
1. 继承Thread类并重写run方法
public class ThreadTest{
    public static void main(String[] args){
        Thread1 t1 = new Thread1("first thread");
        Thread2 t2 = new Thread2("second thread");
        System.out.println(t1.getName());
        System.out.println(t2.getName());
        t1.start();
        t2.start();
    }
}
class Thread1 extends Thread{
    public Thread1(String name){
        super(name);
    }
    @Override
    public void run(){
        for(int i = 0; i < 100; i++){
            System.out.println("hello world: " + i);
        }
    }
}
class Thread2 extends Thread{
    public Thread2(String name){
        super(name);
    }
    @Override
    public void run(){
        for(int i = 0; i < 100; i++){
            System.out.println("welcome: " + i);
        }
    }
}


2. 定义实现runnable接口的类进而实现run方法
public class ThreadTest2{
    public static void main(String[] args){
//        Thread t1 = new Thread(new Runnable()
//        {
//            @Override
//            public void run()
//            {
//                for(int i = 0; i < 100; i++)
//                {
//                    System.out.println("hello :" + i);
//                }
//            }
//        });
//        t1.start();
        Thread t1 = new Thread(new MyThread());
        t1.start();
        Thread t2 = new Thread(new MyThread2());
        t2.start();
    }
}
class MyThread implements Runnable{
    @Override
    public void run(){
        for(int i = 0; i < 100; i++){
            System.out.println("hello :" + i);
        }
    }
}
class MyThread2 implements Runnable{
    @Override
    public void run(){
        for(int i = 0; i < 100; i++){
            System.out.println("welcome: " + i);
        }
    }
}


2. 线程
1) Thread类也实现了Runnable接口,因此实现了Runnable接口中的run方法;
2) 当生成一个线程对象时,如果没有为其设定名字,那么线程对象的名字将使用如下形式:Thread-number,该number将是自动增加的,并被所有的Thread对象所共享(因为它是static的成员变量)。
3) 当使用第一种方式来生成线程对象时,我们需要重写run方法,因为Thread类的run方法此时什么事情也不做。
4) 当使用第二种方式来生成线程对象时,我们需要实现Runnable接口的run方法,然后使用newThread(newMyThread())(假如MyThread已经实现了Runnable接口)来生成线程对象,这时的线程对象的run方法就会调用MyThread类的run方法,这样我们自己编写的run方法就执行了。

停止线程要重新构造方法,不能使用stop()方法。


3. 线程变量
HelloThread中i定义的位置。
线程的全局变量只有一个,而局部变量每一个都会有一个。
关于成员变量与局部变量:如果一个变量是成员变量,那么多个线程对同一个对象的成员变量进行操作时,他们对该成员变量是彼此影响的(也就是说一个线程对成员变量的改变会影响到另一个线程)。
public class ThreadTest3{
    public static void main(String[] args){
        Runnable r = new HelloThread();
        Thread t1 = new Thread(r);
        //r = new HelloThread();
        Thread t2 = new Thread(r);
        t1.start();
        t2.start();
    }
}
class HelloThread implements Runnable{
    int i;
    @Override
    public void run(){
        int i = 0;
        while(true){
            System.out.println("number: " + this.i++);
            try{
                Thread.sleep((long)(Math.random() * 1000));
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
            if(50 == this.i){
                break;
            }
        }
    }
}

4. Synchronized关键字
当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。
public class FetchMoney{
    public static void main(String[] args){
        Bank bank = new Bank();
        Thread t1 = new MoneyThread(bank); // 柜台
        //bank = new Bank();
        Thread t2 = new MoneyThread(bank); // 取款机
        t1.start();
        t2.start();
    }
}
class Bank{
    private int money = 1000;
    public synchronized int getMoney(int number){
        if(number < 0){
            return -1;
        }
        else if(number > money){
            return -2;
        }
        else if(money < 0){
            return -3;
        }
        else{
            try{
                Thread.sleep(1000);
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
            money -= number;
            System.out.println("left money: " + money);
            return number;
        }        
    }
}
class MoneyThread extends Thread{
    private Bank bank;
    public MoneyThread(Bank bank){
        this.bank = bank;
    }
    @Override
    public void run(){
        System.out.println(bank.getMoney(800));
    }
}

Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor),当访问某个对象的synchronized方法时,表示将该对象上锁,此时其他任何线程都无法再去访问该synchronized方法了,直到之前的那个线程执行方法完毕后(或者是抛出了异常),那么将该对象的锁释放掉,其他线程才有可能再去访问该synchronized方法。

如果一个对象有多个synchronized方法,某一时刻某个线程已经进入到了某个synchronized方法,那么在该方法没有执行完毕前,其他线程是无法访问该对象的任何synchronized方法的。
public class ThreadTest4{
    public static void main(String[] args){
        Example example = new Example();
        Thread t1 = new TheThread(example);
        // 区分一个对象还是两个对象
        // example = new Example();
        Thread t2 = new TheThread2(example);
        t1.start();
        t2.start();
    }
}
class Example{
    //static对顺序的影响
    public synchronized void execute(){
        for(int i = 0; i < 20; i++){
            try{
                Thread.sleep((long)(Math.random() * 1000));
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("hello: " + i);
        }
    }
    //static对顺序的影响
    public synchronized void execute2(){
        for(int i = 0; i < 20; i++){
            try{
                Thread.sleep((long)(Math.random() * 1000));
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("world: " + i);
        }
    }
}
class TheThread extends Thread{
    private Example example;
    public TheThread(Example example){
        this.example = example;
    }
    @Override
    public void run(){
        this.example.execute();
    }
}
class TheThread2 extends Thread{
    private Example example;
    public TheThread2(Example example){
        this.example = example;
    }
    @Override
    public void run(){
        this.example.execute2();
    }
}
1) Static方法是属于类的,不是属于对象的。它对应的对象是class对象。
   一个类有两个synchronized static方法,则先执行一个,后执行另一个。
2) 如果某个synchronized方法是static的,那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是synchronized方法所在的对象所对应的Class对象,因为Java中无论一个类有多少个对象,这些对象会对应唯一一个Class对象,因此当线程分别访问同一个类的两个对象的两个static,synchronized方法时,他们的执行顺序也是顺序的,也就是说一个线程先去执行方法,执行完毕后另一个线程才开始执行。


5. Synchronized块
Synchronized块(比synchronized方法更加细粒度)对object进行上锁(传入的object是否是一个object)。
public class ThreadTest5{
    public static void main(String[] args){
        Example2 e = new Example2();
        TheThread3 t1 = new TheThread3(e);
        e = new Example2();
        TheThread4 t2 = new TheThread4(e);
        t1.start();
        t2.start();
    }
}
class Example2{
    private Object object = new Object();
    public void execute(){
        synchronized (this){
            for (int i = 0; i < 20; i++){
                try{
                    Thread.sleep((long) (Math.random() * 1000));
                }
                catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println("hello: " + i);
            }
        }
    }
    public void execute2(){
        synchronized(this){
            for (int i = 0; i < 20; i++){
                try{
                    Thread.sleep((long) (Math.random() * 1000));
                }
                catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println("world: " + i);
            }
        }
    }
}
class TheThread3 extends Thread{
    private Example2 example;
    public TheThread3(Example2 example){
        this.example = example;
    }
    @Override
    public void run(){
        this.example.execute();
    }
}
class TheThread4 extends Thread{
    private Example2 example;
    public TheThread4(Example2 example){
        this.example = example;
    }
    @Override
    public void run(){
        this.example.execute2();
    }
}
两个对象一定的乱序的。


6. 死锁(deadlock)
wait方法,调用必须在synchronized方法或块当中。
public class Sample{
    private int number;
    public synchronized void increase(){
        while (0 != number){
            try{
                wait();
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        number++;
        System.out.println(number);
        notify();
    }
    public synchronized void decrease(){
        while (0 == number){
            try{
                wait();
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        number--;
        System.out.println(number);
        notify();
    }
}
public class IncreaseThread extends Thread{
    private Sample sample;
    public IncreaseThread(Sample sample){
        this.sample = sample;
    }
    @Override
    public void run(){
        for(int i = 0; i < 20; i++){
            try{
                Thread.sleep((long)(Math.random() * 1000));
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
            sample.increase();
        }
    }
}
public class DecreaseThread extends Thread{
private Sample sample;
    public DecreaseThread(Sample sample){
        this.sample = sample;
    }
    @Override
    public void run(){
        for(int i = 0; i < 20; i++){
            try{
                Thread.sleep((long)(Math.random() * 1000));
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
            sample.decrease();
        }
    }
}
public class MainTest{
    public static void main(String[] args){
        Sample sample = new Sample();
        Thread t1 = new IncreaseThread(sample);
        Thread t2 = new DecreaseThread(sample);
        Thread t3 = new IncreaseThread(sample);
        Thread t4 = new DecreaseThread(sample);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
4个线程的时候wait之后还需要判断用while不用if。


7. 说明
wait与notify方法都是定义在Object类中,而且是final的,因此会被所有的Java类所继承并且无法重写。这两个方法要求在调用时线程应该已经获得了对象的锁,因此对这两个方法的调用需要放在synchronized方法或块当中。当线程执行了wait方法时,它会释放掉对象的锁。

另一个会导致线程暂停的方法就是Thread类的sleep方法,它会导致线程睡眠指定的毫秒数,但线程在睡眠的过程中是不会释放掉对象的锁的。


8. 单例模式
对于单例模式(Singleton)来说,如果在getInstance()方法中生成Singleton实例则可能会产生同步问题,即可能会生成两个不同的对象。
public class Singleton{
    private static Singleton singleton;
    private Singleton(){}
    public static Singleton getInstance(){
        if (null == singleton){
            try{
                Thread.sleep((long) (Math.random() * 4000));
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
            singleton = new Singleton();
        }
        return singleton;
    }
    public static void main(String[] args){
        new MyThread().start();
        new MyThread().start();
    }
}
class MyThread extends Thread{
    @Override
    public void run(){
        System.out.println(Singleton.getInstance());
    }
}
运行结果:
code17.Singleton@1fa1bb6
code17.Singleton@1315d34
上一篇: Java中TCP和UDP 下一篇: 没有下一篇了!
发表评论
用户名: 匿名