详细学一学线程和创建线程吧

程序、进程、线程

  1. 程序:静态的代码,安装到硬盘上

  2. 进程:运行中的程序,是操作系统分配资源的最小单位

  3. 线程:线程是进程(程序)中最小的执行单元,是操作系统进行任务调度的最小单位是CPU进行调度的最小单位.

进程和线程的关系

  1. 一个进程可以包含多个线程,一个线程只能属于一个进程,线程不能脱离进程而独立运行

  2. 每一个进程至少包含一个线程(称为主线程);在主线程中开始执行程序, java 程序的入口main()方法就是在主线程中被执行的.

  3. 在主线程中可以创建并启动其它的线程;

  4. 一个进程内的所有线程共享该进程的内存资源。

以QQ聊天为例,登录QQ后我们可以打开多个聊天窗口,同时和张三、李四、王五...聊天. 登录QQ就是通过主线程启动了QQ这个进程,相当于进入main()方法.而我们打开多个聊天窗口相当于创建了多个线程,这些线程都隶属于QQ这个进程.如图:

一个简单的线程

创建包:com.ffyc.javathread包

创建类:Sample类

package com.ffyc.javathread;
public class Sample {
    //方法1
	public void method1(){
    	System.out.println("method1");
	}
    //方法2
	public void method2(){
    	method1();
    	System.out.println("method2");
	}
    /**
    *主方法(主线程),程序的入口
    * 这不是多线程案例,是单线程
    * @param args
    */    
	public static void main(String[] args) {
    	System.out.println("主线程开始");
    	Sample s = new Sample();
    	s.method2();
    	System.out.println("主线程结束");
    }
}

这是一个单线程的典例,输出的结果为:

主线程开始

method1

method2

主线程结束

在类中,从main()方法进入程序,首先打印输出:"主线程开始";然后创建了Sample这个类的对象,调用该类里的方法:method2()-->进入该方法,method2()方法调用了方法:method1()-->进入该方法,执行method1()的方法体:打印输出"method1",执行完method1()后,返回method2()中继续向后执行,打印输出:"method2",执行完method2()方法体后返回到主方法,执行面的语句,输出:"主线程结束".如图:

调用的过程可以用下图表示:

 

显然,整个程序是顺着一条线完成的,这是一个典型的单线程.

创建线程

创建线程有两种方式,我们依次介绍:

  1. 继承Thread类的方式

  2. 实现Runnable接口的方式

一、继承Thread类的方式

  1. 在Java中要实现线程,最简单的方式就是扩展Thread类,重写其中的run方法,方法原型如下:

  1. Thread类中的run方法本身并不执行任何操作,如果我们重写了run方法,当线程启动时,它将执行 run方法。

  2. main()方法也是一个线程,还是启动程序的主线程,所以下面的main()方法中,start()方法启动ThreadDemo线程后,就有两个线程.这两个线程的运行没有固定的先后顺序,由操作系统的调度决定.

创建包:com.ffyc.javathread.demo1

创建类:test

创建类:ThreadDemo

package com.ffyc.javathread.demo1;

//ThreadDemo类
public class ThreadDemo extends Thread{

    /* 要在线程中执行的任务,重写在Thread类的run()方法中,线程要执行的操作*/
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("ThreadDemo"+i);  
        }
    }
}

//Test测试类
public class Test {
    /* 启动java程序的主线程*/
    public static void main(String[] args) {
        /*在主线程中创建线程并启动 */
        ThreadDemo td = new ThreadDemo();  //创建线程
        /*td.run();
        切忌调用run()启动线程
        这只是一个普通的方法调用,即ThreadDemo类的对象调用该对象中的方法,不是启动线程
        启动线程有特定的方法 : start()
        */
        td.start();
/*start()方法才是启动线程的方法,底层调用start0()方法,这是一个native方法(本地方法),由操作系统分配*/
        
        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
        }

    }
}


.***run()方法重写的内容就是线程启动后要执行的内容.main()方法执行时:

  1. 创建了一个ThreadDemo对象,此时是创建了一个线程(ThreadDemo这个类继承(extends)了Thread类,重写了run()方法)

  2. 调用Start()方法启动线程

  3. 此时main()方法的主线程和刚启动的另一个线程由CPU调度执行,没有固定的先执行哪个,后执行哪个

  4. main线程要执行的是:

 for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
  }

td线程要执行的是run()方法中的:

for (int i = 0; i < 1000; i++) {
            System.out.println("ThreadDemo"+i);  
}

他们交替执行的结果可以自己运行看一下.

二、实现Runnable接口的方式

     1. java.lang.Runnable接口中仅仅只有一个抽象方法:

public void run();

 

     2. 也可以通过实现Runnable接口的方式来实现线程,只需要实现其中的run方法即可;

     3. Runnable接口的存在主要是为了解决Java中不允许多继承的问题

如果使用继承(extends)Thread类的方式实现创建一个进程,那么这个类将不能再继承其他的类,但是如果是实现接口,那么可以实现多个接口,且不影响继承想继承的类.

***实现runnable接口的方法:

public class MyThread implements runnable{
    @Override
    public void run(){
        方法体;
    }
}

***创建接口的关键语句:

MyThread r = new MyThread();
//创建一个对象
Thread thread = new Thread(r);/*创建一个线程作为外壳,将r包起来*/
thread.start();/*启动线程*/

二、举个例子

创建包:package com.ffyc.javathread.demo2

创建类:Test类

创建类:MyThread类

package com.ffyc.javathread.demo2;

public class MyThread implements Runnable {
/*
* 我们自己写的MyThread类实现Runnable接口,这个不叫线程类
* 只能叫线程要执行的任务
* MyThread myThread = new MyThread();
* myThread . 不出start方法,无法启动线程
* */
    @Override
    public void run() {
    /*输出的内容:用线程类Thread调用currentThread()方法获取当前的线程,
    再调用getName()方法获取该线程的名字+获取到的线程得我优先级*/
 System.out.println(Thread.currentThread().getName()+Thread.currentThread().getPriority());

    }
}
package com.ffyc.javathread.demo2;


/*
  线程的默认优先级是5,但是也可以通过get
 */
public class Test {
    public static void main(String[] args) {
        /*MyThread myThread = new MyThread();
                 myThread. 不出start方法,无法启动线程
                 */
        MyThread myth = new MyThread();//创建对象

        Thread th = new Thread(myth,"窗口1");  
        //创建了一线程,并为这个线程分配了一个任务,创建线程名称:"窗口1"
        th.start();//启动线程

        Thread th2 = new Thread(myth);  //创建第二个线程
        th2.setName("窗口2");  //用setName()方法为线程命名:"窗口2"
        th2.start();  //启动线程th2

        Thread.currentThread().setPriority(10);获取当前线程,并给它设置优先级:10
        th.setPriority(8);//给th线程设置优先级 8
        th2.setPriority(6);//给th2设置优先级 6

        System.out.println("main"+Thread.currentThread().getPriority());
        //输出main方法(主线程)的优先级
        
    }
}

上面的部分main()方法中有3个线程:main()方法的主线程,th线程和th2线程.三者的先后顺序也是有CPU的调度决定的.

线程的常用类

1. 构造方法;  //构造方法之间的调用 用的是this(所调用的构造方法的参数列表)
2. run(); 用于线程执行的任务  
3. start(); 用于启动线程
4. Thread.currentThread() 用于获得当前线程的引用
5. getName();  获得线程的名字
7. setName();给线程命名

 常用类请大家自己尝试使用~

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像太阳啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值