Thread 线程的创建与方法

115 阅读6分钟

一、进程

进程是一个独立运行的应用程序。比如电脑软件,qq、微信等,启动起来以后,就是一个进程

进程 需要系统进行资源分配,可以获取当前系统内存,网卡,显卡等

进程的特点:

1.独立性 各个进程之间是互相独立的,互相不影响的。

2.互斥性 每个应用程序(软件),系统为其分配一个独立的端口号。如果QQ软件端口号97,IDEL端口号也是97,系统在调97号时只能有一个运行。

写代码Demo1里的main主函数,Demo1可以看成一个应用程序,就是一个进程。

二、线程

进程是由至少一个或者多个线程组成的。线程是进程的最小基本单位。

线程的特性:

1.抢占式运行【重要】 给程序分配CPU,是按照时间片来执行,单位时间片抢占式执行。是随机抢占的。

2.资源共享 同一个进程,有多个线程。这多个线程是可以共享同一个数据的

Demo1可以看成一个进程,

一个Java程序中有两个线程:

1.main主线程

2.垃圾回收线程

三、并行和并发

并行:两个或者多个事件在 同⼀时刻 发生。

并发:两个或多个事件在 同⼀时间间隔 发生。

并行是真正意义上,同⼀时刻做多件事情,而并发在同⼀时刻只会做⼀件事件,只是可以将时间切碎,交替做多件事情。

四、创建线程的两种方式

Java虚拟机允许应用程序同时执行多个线程

1.第一种创建方式

创建线程的第一种方式:

是将一个类声明为Thread类的子类。 这个子类应该重写Thread 类下的run方法。 然后可以分配并启动子类的实例。

package cpm.qf.a_Thread;
​
//1.将一个类声明为Thread类的子类
class MyThread1 extends Thread{
    //2.重写run方法
    @Override
    public void run() {
        for(int i = 1;i<=10; i++){
            System.out.println("MyThread1线程 "+i);
        }
    }
}
class MyThread2 extends Thread{
    @Override
    public void run() {
        for(int i = 1; i<=10; i++){
            System.out.println("MyThread2线程 "+i);
        }
    }
}
public class Demo3 {
    public static void main(String[] args) {
        //3.新建线程的实例
        MyThread2 myThread2 = new MyThread2();
        //4。启动线程
        myThread2.start();
        MyThread1 myThread1 = new MyThread1();
        myThread1.start();
        for(int i = 1; i<=10;i++){
            System.out.println("主线程 "+i);
        }
    }
}

练习:新建两个线程,一个线程打印99乘法表,另外一个线程打印直角三角形

package cpm.qf.a_Thread;
​
class MyThread3 extends Thread{//九九乘法表
    @Override
    public void run() {
        for(int i = 1; i<=9; i++){
            for(int j = 1;j<= i; j++){
                System.out.print(j+"*"+i+"="+j*i+"\t");
            }
            System.out.println();
        }
    }
}
class MyThread4 extends Thread{//打印直角三角形
    @Override
    public void run() {
        for(int i = 1; i<=4; i++){
            for(int j = 1;j<=i; j++){
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
public class Demo4 {
    public static void main(String[] args) {
        new MyThread3().start();
        new MyThread4().start();
    }
}

2.第二种创建方式

创建线程的第二种方式

创建一个线程,作为Runnable接口的实现类,并实现run方法。 然后可以分配类的实例,在创建Thread时作为参数传递,并启动。

package cpm.qf.a_Thread;
​
//声明一个实现Runnable接口的类
class MyThread5 implements Runnable{
    @Override
    public void run() {
        for(int i = 0; i<100; i++){
            System.out.println("MyThread5 "+i);
        }
    }
}
class MyThread6 implements Runnable{
    @Override
    public void run() {
        for(int i = 0; i<100; i++){
            System.out.println("MyThread6 "+i);
        }
    }
}
public class Demo5 {
    public static void main(String[] args) {
        MyThread5 myThread5 = new MyThread5();
        //在创建Thread时作为参数传递并启动
        new Thread(myThread5).start();
        new Thread(new MyThread6()).start();
    }
}

练习:新建两个线程,一个线程打印99乘法表,另外一个线程打印直接三角形

package cpm.qf.a_xiancheng;
​
public class Demo7 {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 1; i<10;i++){//九九乘法表
                    for(int j=1; j<=i; j++){
                        System.out.print(j+"*"+i+"="+j*i+"\t");
                    }
                    System.out.println();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int m = 1;m<5;m++){
                    for(int n = 1;n<=2*m-1; n++){
                        System.out.print("*");
                    }
                    System.out.println();
                }
            }
        }).start();
    }
}

/*

在开发中使用第二种方式,为什么?

第一种方式:继承Thread类,只能单继承

第二种方式:实现Runnable接口,一个类可以实现多个接口

*/

示例:

package cpm.qf.a_xiancheng;
​
class Person{
    
}
class Man extends Person implements Runnable{
    @Override
    public void run() {
        
    }
}
class Woman extends Person implements Runnable{
    @Override
    public void run() {
        
    }
}
public class Demo8 {
    public static void main(String[] args) {
        
    }
}

五、线程下的方法

1.构造方法

Thread()//分配一个新的Thread对象
Thread(Runnable target)
//分配一个新的Thread对象,第二种创建的形式
Thread(Runnable target, String name)
//分配一个新的Thread对象,并对这个线程起一个名字

2.方法

static Thread currentThread()
//返回对当前正在执行的线程对象的引用
String getName()
//返回此线程的名字
void setName(String name)
//将此线程名称改为参数name
package com.qf.mothed_Thread;
​
class MyThread1 implements Runnable{
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        //MyThread1默认的名字 Thread-0
        System.out.println(thread.getName());
    }
}
class MyThread2 implements Runnable{
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        //MyThread2默认的名字 Thread-1
        System.out.println(thread.getName());
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();//获取当前线程对象
        System.out.println(thread.getName());//获取此线程的名字 main
        Thread thread1 = new Thread(new MyThread1(),"二狗");//二狗
        thread1.start();
        new Thread(new MyThread2()).start();//Thread-0
    }
}
int getPriority();
//返回此线程的优先级
void setPriority(int newPriority)
//更改此线程的优先级
static void sleep(long millis)
//使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)
package com.qf.mothed_Thread;
​
class MyThread3 implements Runnable{
    @Override
    public void run() {
        for(int i = 0;i<=10;i++){
            System.out.println("优先级是1的:"+i);
        }
    }
}
class MyThread4 implements Runnable{
    @Override
    public void run() {
        for(int i= 0;i<=10;i++){
            System.out.println("优先级是10的:"+i);
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();//获取当前线程(main)对象的引用
        System.out.println(thread.getPriority());//获取当前线程的优先级为5
​
        Thread thread1 = new Thread(new MyThread3());
        thread1.setPriority(1);
        thread1.start();
​
        Thread thread2 = new Thread(new MyThread4());
        thread2.setPriority(10);
        thread2.start();
    }
}

这里开启两个线程,从优先级来看,优先级为10的线程应该更早执行完,但是还是抢占,结果不可预测,接下来试试为其中一个线程加上sleep()

package com.qf.mothed_Thread;
​
class MyThread3 implements Runnable{
    @Override
    public void run() {
        for(int i = 0;i<=10;i++){
            System.out.println("优先级是1的:"+i);
        }
    }
}
class MyThread4 implements Runnable{
    @Override
    public void run() {
        /*
         为什么 Thread.sleep(1000); 只能try-catche而不能throws呢?
         run方法是重写的方法,重写public abstract void run();
         重写有严格限定,名字,参数,返回值都不能变,限定严格
        */
        try{
                Thread.sleep(1000);//休眠1000毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        for(int i= 0;i<=10;i++){
            System.out.println("优先级是10的:"+i);
        }
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();//获取当前线程(main)对象的引用
        System.out.println(thread.getPriority());//获取当前线程的优先级为5
​
        Thread thread1 = new Thread(new MyThread3());
        thread1.setPriority(1);
        thread1.start();
​
        Thread thread2 = new Thread(new MyThread4());
        thread2.setPriority(10);
        thread2.start();
    }
}

这里为优先级高的线程添加sleep(),让其休眠1秒。可以看到,1秒的时间差,足以让优先级为1的线程早于优先级更高的线程(优先级为10)执行结束。

完结,撒花~