在了解多线程之前,我们先认识一下进程
进程:当前正在运行的程序,可以理解为一个应用程序在内存中的执行区域。比如我们在电脑中打开任务管理器就可以看到后台有许多进程在执行。
线程:线程其实就是进程中的一个执行控制单元,也就是它的执行路径
在一个进程中可以有一个线程,也可以有多个线程。
多线程:执行效率高,但是安全性不高
单线程:执行效率低,但是安全性高
在JAVA中,我们学习多线程主要涉及的是Thread类
创建新执行线程有两种方法。
(1)将类声明为 Thread
的子类。该子类应重写 Thread
类的 run
方法。接下来可以分配并启动该子类的实例。下来看一个例子:
public class Mythread extends Thread { //Mythread为Thread的子类,重写run方法
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++) {
System.out.println(i);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
MyThread mt=new MyThread(); //创建线程实例
mt.start(); //启动线程。注意,我们启动用的是start方法
}
}
//运行的结果就是输出0-49之间的数
上面知识创建了一个单线程的例子,不能看出来多线程之间是如何执行的,所以我们创建多个线程,并且给其指定名字
public class MyThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<5;i++) {
System.out.println(getName()+": "+i); //通过调用getName()方法获取线程名
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
//创建线程实例
MyThread mt=new MyThread();
//启动线程
mt.start();
MyThread mt2=new MyThread();
mt2.start();
}
}
/*
输出结果为
Thread-0: 0
Thread-1: 0
Thread-0: 1
Thread-0: 2
Thread-1: 1
Thread-0: 3
Thread-1: 2
Thread-0: 4
Thread-1: 3
Thread-1: 4
*/
我突然觉得这个名字不好看,想自己给线程设置名字,该怎么办呢?这个时候我们就试用到了void setName(String name)这个方法
public class ThreadDemo {
public static void main(String[] args) {
//创建线程实例
MyThread mt=new MyThread();
//修改线程名字
mt.setName("霉霉");
//启动线程
mt.start();
MyThread mt2=new MyThread(); //创建线程实例
mt2.setName("傻脸娜"); //修改线程名字
mt2.start(); //启动线程
}
}
/*
霉霉: 0
霉霉: 1
傻脸娜: 0
霉霉: 2
傻脸娜: 1
霉霉: 3
傻脸娜: 2
霉霉: 4
傻脸娜: 3
傻脸娜: 4
*/
这里有一点要注意,我们平时用的主方法它是单线程的!!!
(2)创建线程的另一种方法是声明实现 Runnable
接口的类。该类然后实现 run
方法。然后可以分配该类的实例,在创建 Thread
时作为一个参数来传递并启动。
public class MyThread implements Runnable {
@Override
public void run() {
for(int i=0;i<5;i++) {
Thread t=Thread.currentThread();
System.out.println(t.getName()+": "+i);
//我们也可以采用链式编程来实现
System.out.println(Thread.currentThread().getName()+": "+i);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
//创建线程实例
MyThread mt=new MyThread(); //先整一个Runnable类的实现对象
Thread t=new Thread(mt);
//修改线程名字
t.setName("泰勒斯");
//启动线程
t.start();
//创建线程实例
MyThread mt2=new MyThread();
Thread t2=new Thread(mt);
t2.setName("傻脸娜"); //修改线程名字
t2.start(); //启动线程
}
}
/*泰勒斯: 0
傻脸娜: 0
泰勒斯: 1
泰勒斯: 2
傻脸娜: 1
泰勒斯: 3
傻脸娜: 2
泰勒斯: 4
傻脸娜: 3
傻脸娜: 4
*/
这里我们有一个方法
static Thread currentThread()
/*用来返回当前线程对象。上面的例子我们不能直接使用getName()所以先创建的Thread对象,用它来调用getNmae()*/
看完上面两种创建线程的方法,我们可能会有这样一个疑问,既然有了继承Thread为什么还要整出来一个Runnable接口呢?这不是多此一举嘛!不妨回想一下我们前面学到的知识,在JAVA中,只有单继承,如果我们使用了继承Thread方法的话,后面我们想要继承其它类的话就不可能了,所以我们推荐使用第二种创建线程的方法。