今天,我们来谈一谈Java里的线程。
一、进程与线程的基本概念
大家可能没听过线程这个概念,但是相信,用计算机的朋友都听过进程这个概念。打开电脑的任务管理器,我们就可以看到许多进程。它们主要分为三类,应用进程、后台进程与windows进程。我们可以把进程称为程序运行的一个单位,而线程,就是一个比进程还小的运行单位。
引用一段百度而来的关于进程与线程的资料:
进程和线程都是由操作系统所体现的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。
进程和线程的区别在于:
简而言之,一个程序至少有一个进程,一个进程至少有一个线程。
二、多线程的概念
知道了线程是什么,接下来我们来讲一讲多线程的概念。多线程,顾名思义,就是多个线程一起工作。我看过这么一种举例,这里借来用作说明。就好比吃饭,单进程单线程,就是一个人在一张桌子上吃饭。单进程多线程,就是多个人在一个桌子上吃饭。多进程多线程,就是多个人在多张桌子上吃饭。使用多线程的好处在于能够提高程序的效率。但是,对于一个线程来说,创建它需要一定的内存,运行也会消耗CPU的资源。对于我们普通电脑的内存和CPU来说,线程显得有些“昂贵”。就好比吃饭,多个人在一个桌子上吃饭难免会有拥挤。因此,实际上,多线程的运行方式并非多个线程同时运行。而是对于一段时间来说,分为若干个极小的时间片,然后给不同的线程分配不同的时间片去让它运行。然而,这个时间过于短暂,所以我们可以看成是多个线程一块运行。
三、线程的创建
按照进程与线程的定义来看,一个程序最少有一个进程,一个进程最少有一个线程。然而,事实上,在我们自行编写一些应用程序,诸如画图板和五子棋的时候,我们并没有用到所谓的线程。这似乎与线程的概念有所违背。事实上,对于上述缩写的代码,并不是由我们去创建的线程,而是Java虚拟机帮我们创建的线程。
接下来进入我们的主题——创建线程。
创建线程有两种方法。
1、实现Runnable接口。
2、继承Thread类。
首先,我们来看第一种。实现接口我们之前有提到,implements。之后,我们需要在该类中重写Runnable类里的抽象方法。我们可以看到,在Runnable接口里,有一个名为run的抽象方法。我们需要做的是重写run方法,之后,通过调用run方法的方式,告诉Java虚拟机运行我们创建的线程。
具体代码如下:
1 package thread; 2 public class Runnablelh implements Runnable{ 3 public static void main(String[] args) { 4 Runnablelh ll=new Runnablelh(); 5 ll.run(); 6 } 7 public void run() { 8 System.out.println("-------------"); 9 } 10 }
不过,我们常用的多为第二种方式。Thread类是API中一个实现了Runnable接口的类,不过在Thread类中添加了一些与线程操作相关的方法。比如start、sleep等等。这里,我们不再调用run方法,而是改为调用start方法告诉虚拟机运行我们的线程。
给出一段代码:
1 package thread; 2 public class threadtext extends Thread{ 3 public static void main(String[] args) { 4 for(int i=0;i<5;i++){ 5 threadtext t=new threadtext(); 6 t.start(); 7 } 8 } 9 public void run(){ 10 System.out.println("线程"+Thread.currentThread()+"正在运行"); 11 } 12 }
注意,这里的currentThread方法表示的是输出该线程的名字。线程的名字可以自行设置,若没有设置则是由系统自动提供。
这里注意一个细节,当你运行这段程序的时候,得到的结果可能不完全相同。以下给出两次运行的结果:
之前我们提到过,我们的start与run是告诉Java虚拟机需要运行我们的线程。然而这个时间是不确定的,所以就导致了两次结果的不相同。注意一点,对于一个线程,一般情况下,当你的run方法运行完,那么一个线程就结束了。除非你加上了一些语句使得线程不关闭或者延长其运行时间。
以上,就是我对于线程的一些认识。如有不对之处,请大家指正。