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

关于java线程的一些东西

2016-09-28 11:21 453 查看
一、先简单描叙一下创建线程的方式通过继承Thread:

(1)定义一个类继承Thread类

(2)覆盖Thread类中的run方法

(3)直接创建Thread的子类对象线程

(4)调用start方法开启线程并调用线程的任务run方法执行

[java] view
plain copy

 print?





public class ThreadDemo extends Thread {  

      

    private String name;  

    public ThreadDemo(String name){  

        this.name = name;  

    }  

      

    public void run(){  

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

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

        }  

    }  

      

    public static void main(String[] args) {  

        ThreadDemo demo = new ThreadDemo("李四");  

        ThreadDemo demo1 = new ThreadDemo("张三");  

        demo.start();  

        demo1.start();  

    }  

}  

二、run方法和start方法的区别

1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码:

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

这时此线程是处于就绪状态, 

并没有运行。 

然后通过此Thread类调用方法run()来完成其运行操作的, 

这里方法run()称为线程体, 

它包含了要执行的这个线程的内容, 

Run方法运行结束, 

此线程终止, 

而CPU再运行其它线程, 

 

2.run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码:

 

而如果直接用Run方法, 

这只是调用一个方法而已, 

程序中依然只有主线程--这一个线程, 

其程序执行路径还是只有一条, 

这样就没有达到写线程的目的。 

 

举例说明一下:

记住:线程就是为了更好地利用CPU, 

提高程序运行速率的! 

在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。

描述实现Runnable接口

(一)创建一个类,实现Runnable接口

(二)复写Runnable里面的run方法

(三)实例化这个类,调用start方法,此时线程开启,就执行该线程的run方法

[java] view
plain copy

 print?





class MyThread implements Runnable{  

   

    private int ticket = 5;  //5张票  

   

    public void run() {  

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

            if (this.ticket > 0) {  

                System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);  

            }  

        }  

    }  

}  

  

public class lzwCode {  

       

    public static void main(String [] args) {  

        MyThread my = new MyThread();  

        new Thread(my, "1号窗口").start();  

        new Thread(my, "2号窗口").start();  

        new Thread(my, "3号窗口").start();  

    }  

}  

实现Runnable接口的好处如下:

1.避免了java里面的单继承问题

2.适合多个相同的程序代码的线程去处理同一个资源

3.增加程序的健壮性,代码可以被多个线程共享,代码和数据独立

一、产生线程安全的原因

(1)多个线程在操作共享数据

(2)操作共享数据的线程代码有多条

结论:当一个线程在执行操作共享数据的多条代码过程中,其他线程参与运算,就会导致线程安全问题的产生。

二、解决方案:同步锁,同步锁分为两种如下:

(1)同步锁代码块

[java] view
plain copy

 print?





Synchronized(对象){  

    //code;  

}  

(2)同歩锁函数

[java] view
plain copy

 print?





public synchronized void show(){  

    //code;  

}  

 同步锁函数和同步代码块的区别:

①同步函数的锁是固定的this;

②同步代码块的锁是任意的对象;

③静态的同步函数使用的锁是该函数所属字节码文件对象,可以用getClass()方法获取,也可以用当前类名.class获取;
(3)使用同歩锁的前提:必须有多个线程并同时使用同一个锁;

三、死锁原因

(1)同步锁嵌套

[java] view
plain copy

 print?





synchronized(MyLocked.locka){  

    System.out.println(Thread.currentThread().getName()+" if locka....");  

    synchronized(MyLocked.lockb){  

        System.out.println(Thread.currentThread().getName()+" if lockb....");  

    }  

}  

(2)线程间的通讯,多个线程在处理同一个资源,但任务却不同

[java] view
plain copy

 print?





//资源  

class Resource  

{  

    String name;  

    String sex;  

}  

  

  

//输入  

class Input implements Runnable  

{  

    Resource r ;  

//  Object obj = new Object();  

    Input(Resource r)  

    {  

        this.r = r;  

    }  

    public void run()  

    {  

        int x = 0;  

        while(true)  

        {  

            synchronized(r)  

            {  

                if(x==0)  

                {  

                    r.name = "mike";  

                    r.sex = "nan";  

                }  

                else  

                {  

                    r.name = "丽丽";  

                    r.sex = "女女女女女女";  

                }  

            }  

            x = (x+1)%2;  

  

        }  

    }  

}  

//输出  

class Output implements Runnable  

{  

  

    Resource r;  

//  Object obj = new Object();  

    Output(Resource r)  

    {  

        this.r = r;  

    }  

  

    public void run()  

    {  

        while(true)  

        {  

            synchronized(r)  

            {  

                System.out.println(r.name+"....."+r.sex);  

            }  

        }  

    }  

}  

  

  

  

class  ResourceDemo  

{  

    public static void main(String[] args)   

    {  

        //创建资源。  

        Resource r = new Resource();  

        //创建任务。  

        Input in = new Input(r);  

        Output out = new Output(r);  

        //创建线程,执行路径。  

        Thread t1 = new Thread(in);  

        Thread t2 = new Thread(out);  

        //开启线程  

        t1.start();  

        t2.start();  

    }  

}  

四、等待/唤醒机制

(1)wait();让线程处于冻结状态,被wait的线程会被存储到线程池中;

(2)notify();唤醒线程池中一个线程(任意);

(3)notifyAll();唤醒线程池中的所有线程;

总结:这些方法都必须能定义在同步锁中,因为这些方法是用于操作线程状态的方法,必须能要明确到底操作的是哪个锁上的线程

为什么操作线程的方法wait notify notifyAll定义在了Object类中? 

因为这些方法是监视器的方法。监视器其实就是锁。锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。

五、示例如下:

资源类:

[java] view
plain copy

 print?





<span style="font-size:14px;">package com.edu.csu.syn;  

  

public class Resource {  

      

    private String name;  

    private String sex;  

    private boolean flag = false;  

      

    public synchronized void set(String name,String sex){  

        if(flag)  

            try {  

                this.wait();  

            } catch (InterruptedException e) {  

                e.printStackTrace();  

            }  

            this.name = name;  

            this.sex = sex;  

            flag = true;  

            this.notify();  

          

    }  

      

    public synchronized void out(){  

        if(!flag)  

            try {  

                this.wait();  

            } catch (InterruptedException e) {  

                e.printStackTrace();  

            }  

        System.out.println(name+"......"+sex);  

        flag = false;  

        this.notify();  

    }  

}  

</span>  



输入类:


[java] view
plain copy

 print?





<span style="font-size:14px;">package com.edu.csu.syn;  

  

public class Input implements Runnable {  

      

    private Resource r;  

      

    public Input(Resource r){  

        this.r = r;  

    }  

  

    @Override  

    public void run() {  

        int x = 0;  

        while(true){  

            if (x == 0) {  

                r.set("mike", "nan");  

            } else {  

                r.set("丽丽", "女女女女");  

            }  

  

            x = (x + 1) % 2;  

        }  

    }  

  

}</span>  

输出类:

[java] view
plain copy

 print?





<span style="font-size:14px;">package com.edu.csu.syn;  

  

public class Output implements Runnable {  

      

    private Resource r;  

      

    public Output(Resource r){  

        this.r = r;  

    }  

    @Override  

    public void run() {  

        while(true){  

            r.out();  

        }  

    }  

  

}</span>  

测试类:

[java] view
plain copy

 print?





<span style="font-size:14px;">package com.edu.csu.syn;  

  

public class Test {  

  

    /** 

     * @param args 

     */  

    public static void main(String[] args) {  

        //创建资源  

        Resource r = new Resource();  

        //创建任务  

        Input i = new Input(r);  

        Output o = new Output(r);  

        //创建线程,执行任务  

        Thread t = new Thread(i);  

        Thread t1 = new Thread(o);  

        //开启线程  

        t.start();  

        t1.start();  

    }  

  

}  

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