多线程(0)----多线程的概念

版权声明:未经同意,严禁转载 https://blog.csdn.net/pengchengliu/article/details/83063136

                                                                                                                                                      点击此处返回总目录

有关进程、线程的概念回去看操作系统,为了保持结构完整,这里随便写了一点。

一、进程的概念

进程就是正在运行的程序。程序文件存在硬盘上,当运行的时候,进入内存,就变成了一个进程。

二、线程的概念

以前讲的程序中的多个方法都是顺序执行的。从main开始到结尾,一条路走到黑。这种程序称为单线程程序,优点就是没有安全隐患,缺点就是效率堪忧。为了让多个方法同时执行,可以为程序开通多个路径,每一个路径就是一个线程。

就比如说360安全卫士,是一个进程。里面可以同时查病毒,又同时更新软件,这就是多线程。

再比如说迅雷多线程下载,可以开启多个线程同时下载一个文件。

单核CPU一个时刻只能运行一个线程,来回切换。

三、Thread类的使用(创建线程的一种方式)

步骤:首先定义子类,继承Thread,重写父类的run()方法。

           然后在main中,通过new Thread子类的对象,创建进程;调用start()方法执行。

run()方法和start()方法的区别:

    重写的run()方法,我们不自己调用,而是通过start()方法调用。线程对象调用start()方法开启线程,并让jvm调用run()方法在开启的线程中执行。如果线程对象直接调用run()方法,就当做普通方法一样执行。

例:

SubThread.java

package cn.itcast.demo01;

public class SubThread extends Thread{             //要继承Thread类。lang包不需要导包。
    public void run(){                                              //注意重写的run()方法,我们自己不调用。而是由start()方法让虚拟机调用。
        for(int i = 0;i<3;i++){
            System.out.println("thread.."+i);
        }
    }
    
}

Test.java

package cn.itcast.demo01;

public class Test {
    public static void main(String[] args) {
        SubThread st = new SubThread();      //创建线程。就是创建Thread子类的对象。
        st.start();                                              //启动线程。调用的是start()方法,不是run()方法。注意start()方法做的事:一是启动线                                                                         程,二是指挥JVM调用线程中的run()方法。另外,start()方法只能启动一次。
        for(int i = 0;i<3;i++){
            System.out.println("main..."+i);
        }
    }
}

运行结果:

main...0
thread..0
thread..1
thread..2
main...1
main...2

四、Thread类常用方法

1. public String getName()                             //返回该线程的名称。每一个线程都有自己的名字。main线程的名字就叫"main",                                                                                          其他新建的线程叫"Thread-0","Thread-1",...   【例1】

2. public static Thread currentThread()         //返回当前正在执行的线程对象的引用。【例2】【例3】

3. static void sleep(long millis)                       //指定线程睡上多少毫秒。sleep()方法哪里都能写。【例4】【例5】

例1:每一个线程都有默认的名字Thread-0,Thread-1,...

//Thread.java

package cn.itcast.demo01;

public class SubThread extends Thread{
    public void run(){
        //System.out.println(getName());                 //可以在类中调用,也可以使用对象调用。
    }
}

//Test.java

package cn.itcast.demo01;

public class Test {
    public static void main(String[] args) {
        SubThread st = new SubThread();
        System.out.println(st.getName());                  //Thread-0。线程的名字叫Thread-0,不叫st。
        
        SubThread st1 = new SubThread();        
        System.out.println(st1.getName());                //Thread-1
    }
}

例2:如何获取main线程的名字?因为getName()是非静态方法,而main是静态方法,所以main中不能调用getName()方法。再说了,Test类的父类是Object类,不是Thread类,所以也调用不了Thread类的getName()方法。因此不能通过例1的方式在线程中直接调用getname()获得线程的名字。

要想获得住线程的名字,必须先得到主线程的对象,然后通过对象调用getName()方法获得主线程的线程名。

package cn.itcast.demo02;

public class Test {
    public static void main(String[] args) {
        Thread th = Thread.currentThread();
        System.out.println(th.getName());                //main
    }
}

例3:其他线程既可以直接调用getName()获得线程名,也可以先得到线程,然后调用getName()。

//SubThread.java

package cn.itcast.demo02;

public class SubThread extends Thread {
    public void run(){
        Thread th = Thread.currentThread();
        System.out.println(th.getName());                    //Thread-0
    }
}

//Test.java

package cn.itcast.demo02;

public class Test {
    public static void main(String[] args) {
        SubThread st = new SubThread();
        st.start();
    }
}

例4:可以在main中睡眠。

package cn.itcast.demo02;

public class Test {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("aa");
        Thread.sleep(1000);
        System.out.println("bb");
        Thread.sleep(2000);
        System.out.println("cc");
    }
}

例5:也可以在线程中睡眠。

//SubThread.java

package cn.itcast.demo02;

public class SubThread extends Thread {
    public void run(){
        System.out.println("aa");
        try {
            Thread.sleep(1000);
            System.out.println("bb");
            Thread.sleep(2000);
            System.out.println("cc");
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

//Test.java

package cn.itcast.demo02;

public class Test {
    public static void main(String[] args) throws InterruptedException {
        SubThread st = new SubThread();
        st.start();
    }
}

五、创建线程的另一种方式

步骤:

1. 写一个类,实现Runable接口,重写run()方法。

2. 创建Runable接口的实现类的对象。

3. 创建Thread类的对象,在构造方法中传递Runable接口的实现类的对象。

4. 调用Thread类的start()方法。

实现Runable接口的好处(与继承Thread类的方式比较):

1. 实现Runable接口避免了继承Thread类的单继承的局限性。

2. 降低了程序的耦合性。Thread类与Runable接口没有什么联系,也就是将线程与线程任务进行了分离,而继承Thread类的方式是本身就封装了方法,做死了已经。

3. 实现了资源共享。(后面讲)

例:

//SubThread.java

package cn.itcast.demo03;

public class SubThread implements Runnable{
    public void run(){
        System.out.println("aaa");
    }
}

//Test.java

package cn.itcast.demo03;

public class Test {
    public static void main(String[] args) {
        SubThread st = new SubThread();
        Thread th = new Thread(st);
        th.start();
    }
}

六、通过匿名内部类的格式实现线程程序

之前讲过匿名内部类,将上面两种创建线程的方式改成匿名内部类的格式。

package cn.itcast.demo04;

public class Test {
    public static void main(String[] args) {
        //第一种实现线程的方式
        new Thread(){
            public void run(){
                System.out.println("aaa");
            }
        }.start();
        
        //第二种实现线程的方式
        Runnable r = new Runnable(){
            public void run(){
                System.out.println("bbb");
            }
        };
        
        Thread t = new Thread(r);
        t.start();
        
        //第二种实现线程的方式
        new Thread(
            new Runnable(){
                public void run(){
                    System.out.println("ccc");
                }
            }).start();
        
    }
}

七、线程的状态

猜你喜欢

转载自blog.csdn.net/pengchengliu/article/details/83063136
今日推荐