0
点赞
收藏
分享

微信扫一扫

多线程_小记


程序进入内存中运行就变成一个进程,进程具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位。

进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。(进程是资源分配的最小单位)
  线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
  线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。
  多进程是指操作系统能同时运行多个任务(程序)。
  多线程是指在同一程序中有多个顺序流在执行。
在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口.(其实准确来讲,应该有三种,还有一种是实现Callable接口,并与Future、线程池结合使用

多进程的目的是提高CPU的使用率,提高工作效率,多个工作可以同时进行。
在一个进程里,会有多个线程并发执行抢夺cpu的使用权,抢夺概率是随机的。。

注:JVM也是多线程程序,因为其自带垃圾回收器,确保程序不会轻易的造成内存溢出看,所以JVM至少开启两条线程。一是程序会执行main主线程;二是垃圾回收器线程的运行确保程序不会内存异常。

重点:如何实现多线程程序?
* 要实现多线程程序,必须创建一个进程,
* 创建进程需要调用系统资源进行创建,但是Java语言是不能直接调用系统资源
* C/C++语言是可以创建系统资源,然后使用Java语言掉C/C++已经封装好的东西,

多线程程序实现方式1:
1)自定一个类:MyThread 继承自Thread类
2)在MyThread类中重写Thread类中的run()
3)在主线程中,创建该类的实例对象,启动线程

测试类
package Day20_DuoJinCheng;
/**
 * @author Aoman_Hao
 */
public class Test1 {

    public static void main(String[] args) {
        //创建进程
        //无参构造
        UseThread U1 = new UseThread();
        U1.setName("U1");

        //有参构造
        UseThread U2 = new UseThread("U2");

        U1.start();
        U2.start();

    }

}
对象类:
package Day20_DuoJinCheng;
/**
 * @author Aoman_Hao
 */
public class UseThread extends Thread {

    //无参构造
    public UseThread() {
        super();
    }

    //有参构造
    public UseThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for(int i=1;i<20;i++){
            System.out.println("进程"+Thread.currentThread().getName()+"的数字:"+i);
        }
    }
}

输出:进程U2的数字:1
进程U1的数字:1
进程U2的数字:2
进程U1的数字:2
进程U2的数字:3
进程U1的数字:3
进程U2的数字:4
进程U1的数字:4
进程U1的数字:5
进程U1的数字:6
进程U1的数字:7
进程U1的数字:8
进程U1的数字:9
进程U1的数字:10
进程U1的数字:11
进程U1的数字:12
进程U1的数字:13
进程U1的数字:14
进程U1的数字:15
进程U1的数字:16
进程U1的数字:17
进程U1的数字:18
进程U1的数字:19
进程U2的数字:5
进程U2的数字:6
进程U2的数字:7
进程U2的数字:8
进程U2的数字:9
进程U2的数字:10
进程U2的数字:11
进程U2的数字:12
进程U2的数字:13
进程U2的数字:14
进程U2的数字:15
进程U2的数字:16
进程U2的数字:17
进程U2的数字:18
进程U2的数字:19

多线程构建方法2:
1)自定义一个类MyRunnable,该类实现Runnable接口
2)实现该接口中的run()方法
3)在主线程中创建该类的实例对象,
4)创建Thread类对象,将3)创建的这个对象作为参数进行传递
5)分别启动线程

测试类:
package Day20_DuoJinCheng;
/**
 * @author Aoman_Hao
 */
public class RunTest {

    public static void main(String[] args) {
        //创建MyRunnable实例对象
        UseRunnalbe U1 = new UseRunnable();

        //创建Thread有参构造类对象
        Thread T1 = new Thread(U1); 
        T1.setName("T1");

        //一步走
        Thread T2 = new Thread(U1,"T2");

        //启动多线程
        T1.start();
        T2.start();


    }

}
实例对象类:
package Day20_DuoJinCheng;
/**
 * @author Aoman_Hao
 */
public class UseRunnable implements Runnable {


    @Override
    public void run() {
        for(int i=1;i<20;i++){
            //间接的使用Thread类的静态功能得到线程名称
            System.out.println(Thread.currentThread().getName()+"数字:"+i);
        }
    }

}
输出:
T1数字:1
T2数字:1
T1数字:2
T2数字:2
T1数字:3
T2数字:3
T1数字:4
T2数字:4
T1数字:5
T2数字:5
T1数字:6
T2数字:6
T1数字:7
T2数字:7
T1数字:8
T2数字:8
T1数字:9
T2数字:9
T1数字:10
T2数字:10
T1数字:11
T2数字:11
T1数字:12
T2数字:12
T1数字:13
T2数字:13
T1数字:14
T2数字:14
T1数字:15
T2数字:15
T1数字:16
T2数字:16
T1数字:17
T2数字:17
T1数字:18
T2数字:18
T1数字:19
T2数字:19

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。
总结:
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类

public final void join() –throws InterruptedException等待该线程终止。
public final int getPriority()–返回线程的优先级。
public static void yield()–暂停当前正在执行的线程对象,并执行其他线程。

测试类
package Day20_DuoJinCheng;
/**
 * @author Aoman_Hao
 */
public class Demo {

    public static void main(String[] args) {
        //实现Runnable接口的类
        UseRunnable ur = new UseRunnable();

        //创建多线程的类
        Thread T1 = new Thread(ur,"T1"); 
        Thread T2 = new Thread(ur,"T2"); 
        Thread T3 = new Thread(ur,"T3"); 

        //获取优先级等级数
        int p2_pri = T2.getPriority();
        System.out.println(p2_pri);
        //设置优先级等级数
        T2.setPriority(10);
        System.out.println(T2.getPriority());

        //启动多线程
        T1.start();
        //join 等待进程终止
        try {
            T1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        T2.start();
        T3.start();


    }

}

对象类:
package Day20_DuoJinCheng;
/**
 * @author Aoman_Hao
 */
public class UseRunnable implements Runnable {


    @Override
    public void run() {
        for(int i=1;i<20;i++){
            //间接的使用Thread类的静态功能得到线程名称
            System.out.println(Thread.currentThread().getName()+"数字:"+i);
            //public static void yield()暂停当前正在执行的线程对象,并执行其他线程。
            Thread.yield();

        }
    }

}

public final void setDaemon(boolean on) –on指定true,就是设置守护线程…
将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。该方法必须在启动线程前调用。

jvm自动退出,对于主线程的数据如果直接输出完毕,对于两个守护线程来说不会立即消失,Jvm等会就自动退出.
线程停止:
public final void stop():强迫线程停止执行
public void interrupt()中断线程。 表示中断线程一种状态

  • setDeamon(boolean on):(用的多)
  • sleep():线程睡眠 (用的多)
  • wait():线程等待

sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。

测试类:
package Day20_Duo;
/**
 * @author Aoman_Hao
 */
public class Demo2 {

    public static void main(String[] args) {
        CopyUseRunnable C = new CopyUseRunnable();
        Thread t1 = new Thread(C,"T1");
        Thread t2 = new Thread(C,"T2");
        Thread t3 = new Thread(C,"T3");

        //设置t1为守护线程,主程序计算完,守护线程的数据慢慢运行
        t1.setDaemon(true);

        //stop过时了,依旧可用,现在不推荐这种用法
//      t2.stop();

        //public void interrupt()中断线程。 表示中断线程一种状态
        t2.interrupt();

        t1.start();
        t2.start();
        t3.start();


    }

}
对象类:
package Day20_Duo;
/**
 * @author Aoman_Hao
 */
public class CopyUseRunnable implements Runnable {


    @Override
    public void run() {
        for(int i=1;i<20;i++){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //间接的使用Thread类的静态功能得到线程名称
            System.out.println(Thread.currentThread().getName()+"数字:"+i);

        }
    }

}
输出:
T3数字:1
T1数字:1
T2数字:1
T3数字:2
T2数字:2
T1数字:2
T1数字:3
T2数字:3
T3数字:3
T1数字:4
T2数字:4
T3数字:4
T2数字:5
T1数字:5
T3数字:5
T2数字:6
T1数字:6
T3数字:6
T2数字:7
T1数字:7
T3数字:7
T1数字:8
T2数字:8
T3数字:8
T1数字:9
T2数字:9
T3数字:9
T1数字:10
T2数字:10
T3数字:10
T1数字:11
T2数字:11
T3数字:11
T2数字:12
T1数字:12
T3数字:12
T1数字:13
T2数字:13
T3数字:13
T1数字:14
T2数字:14
T3数字:14
T1数字:15
T2数字:15
T3数字:15
T1数字:16
T2数字:16
T3数字:16
T1数字:17
T2数字:17
T3数字:17
T1数字:18
T2数字:18
T3数字:18
T2数字:19
T1数字:19
T3数字:19

t2运行stop,t2线程直接结束,不在运行,抢CPU。


举报

相关推荐

0 条评论