Java线程(一)

在Java语言提供了非常优秀的多线程支持,程序可以通过非常简单的方式来启动多线程。(本篇博客参考相关书籍和自己所知道写出线程的知识点)
进程与线程
几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序就是一个进程。当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程。
多线程则扩展了多进程的概念,使得同一个进行可以同时并发处理多个任务。线程(Thread)也被称作轻量级进程(Ligheweight Process),线程是进程的执行单元。就象进程在操作系统中的地位一样,线程在程序中是独立的、并发的执行流。当进程被初始化后,主线程就被创建了。对于绝大多数的应用程序来说,通常仅要求有一个主线程,但我们也可以在该进程内创建多条顺序执行流,这些顺序执行流就是线程,每条线程也是互相独立的。
线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父进程。线程不再拥有系统资源,它与父进程的其它线程共享该进程所拥有的全部资源。因为多个线程共享父进程里的全部资源,因此编程更加方便;但必须更加小心,我们必须确保线程不会妨碍同一进程里的其它线程。
线程可以完成一定的任务,可与其他线程共享父进程中的共享变量及部分环境、相互之间协同来完成进程所要完成的任务。
简而言之:一个程序运行后至少有一个进程,一个进程里可以包含多个线程,但至少包含一个线程。
多线程编程的优势
1)进程间不能共享内存,但线程之间共享内存非常容易。
2)系统创建进程需要为该进程重新分配系统资源,但创建线程则代价小得多,因此使用多线程来实现多任务并发比多进程的效率高。
3) Java语言内置的多线程功能支持,而不是单纯地作为底层操作系统的调度方式,从而简化了Java的多线程编程。


对线程有个大概了解后,接下来就是要知道怎么创建和启动线程,创建线程有两种方式:

1.继承Thread类
步骤:
(1)定义类继承Thread
(2)复写Thread类中的run方法
目的:将自定义的代码存储在run方法中,让线程运行。
(3)调用线程的start方法,该方法有两个作用:启动线程,调用run方法。
2、创建线程的第二种方式:实现Runnable接口
步骤:
*(1)定义类实现Runnable接口
将线程要运行的代码存放在run方法中
(2)覆盖Runnable接口中的run方法
(3)通过Thread类建立线程对象
(4)将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
因为,自定义的run方法所属的对象是Runnable接口的子类对象,所以要让线程去指定对象的run方法,就必须明确run方法所属对象。
(5)调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
下列用代码演示:
第一种方式:

//通过继承Thread类来创建线程类
public class FirstThread extends Thread{

    //重写run()方法,run()方法的方法体就是线程执行体
    public void run()
    {
        for(int i = 0; i < 100; i++)
        {
            //当线程类继承Thread类时,直接使用this即可获取当前线程
            //Thread对象的getName()返回当前线程的名字
            //因此可以直接使用调用getName()方法返回当前线程的名字
            System.out.println(getName()+" "+i);
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        for(int i = 0; i < 100; i++)
        {
            System.out.println(Thread.currentThread().getName()+" "+i);
            if(i==20)
            {
                new FirstThread().start();//创建并启动第一个线程
                new FirstThread().start();//创建并启动第二个线程
            }
        }
    }
}

运行结果:
这里写图片描述
第二种方式:

public class SecondThread implements Runnable{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(int i = 0; i < 100; i++)
        {
            //当线程类实现Runnable接口时
            //如果想获取当前线程,只能用Thread.currentThread()方法
            System.out.println(Thread.currentThread().getName()+" "+ i);
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        for(int i = 0; i < 100; i++)
        {
            System.out.println(Thread.currentThread().getName()+" "+ i);
            if(i == 20)
            {
                SecondThread st = new SecondThread();
                //通过new Thread(target,name)方法创建新线程
                new Thread(st,"新线程1").start();
                new Thread(st,"新线程2").start();
            }
        }   
    }
}

运行结果:
这里写图片描述
实现方式和继承方式的区别:
实现方式好处:避免了单继承的局限性,在定义线程时,建议使用实现方式。
继承Thread:线程代码存放在Thread子类run方法中,实现Runnable,线程代码存放在接口的run方法中。
运行程序中,我们会发现运行结果每次都不同,因为多个线程都获取cpu的执行权,cpu执行到谁,谁就执行,在某一个时刻,只能有一个程序在运行(多核除外),cpu在做着快速的切换,以达到看上去是同时运行的效果,我们可以形象的把多线程的运行行为看成在互相抢夺cpu的执行权,这就是多线程的一个特性:随机性,谁抢到,谁执行,至于执行多长,cpu说了算。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值