Java多线程入门 (上)
在介绍多线程之前,首先我们要先了解什么叫线程,什么叫进程?
进程和线程介绍
进程其实就是一个应用程序,在我们打开qq,谷歌浏览器,网易云音乐,的时候每打开一个应用程序,就会启动一个进程,那么什么是线程呢?线程其实就是进程中的某一个执行过程,一个进程中可以有多个线程.比如我们打开迅雷软件,它是一个进程,然后我们使用迅雷软件下载文件或某某电影,每一个文件或电影都使用了一个线程,这样可以同时工作,提高效率.
多线程的三种方式
第一种:继承Thread类来使用多线程:
//我们先写一个main方法来调用
public class ThreadDemo01 {
public static void main(String[] args) {
System.out.println("main 方法执行");
CreateDemo01 createDemo = new CreateDemo01();
createDemo.start();
System.out.println("main 方法启动子线程");
for (int i = 0; i < 100; i++) {
System.out.println("main:" + i);
}
}
}
//继承Thread类
class CreateDemo01 extends Thread {
//重写run方法
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("run:" + i);
}
}
}
第二种:实现Runnable接口:
public class ThreadDemo02 {
public static void main(String[] args) {
System.out.println("main方法启动");
CreateDemo02 createDemo = new CreateDemo02();
Thread thread = new Thread(createDemo);
thread.start();
System.out.println("main方法启动子线程");
for (int i = 0; i < 100; i++) {
System.out.println("main:" + i);
}
}
}
//实现Runnable接口
class CreateDemo02 implements Runnable {
//重写run方法
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("run:" + i);
}
}
}
第三种:匿名内部类:
public class ThreadDemo03 {
public static void main(String[] args) {
System.out.println("创建main主线程");
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("run:" + i);
}
}
}).start();
System.out.println("main方法创建子线程");
for (int i = 0; i < 100; i++) {
System.out.println("main:" + i);
}
}
}
在这里不多做三种实现的介绍,这需要注意的是run方法和start方法的使用,可以看见上面的三种代码中都是使用了Thread来调用start方法,而不是调用run方法,因为run方法并不是多线程的启动方法,而想要启动多线程需要使用start方法来调用run方法启动,还有一个问题就是实现Runnable接口的时候不能直接调用start方法,需要先定义一个Thread类进行调用start方法.
常用方法
1.currentThread()
返回当前执行的对象的引用
2.getId()
返回当前线程的id,可以使用setId自定义
3.getName()
返回当前线程的name,可以使用setname自定义
4.sleep()
休眠线程,使用毫秒值来表示休眠时间
5.join()
等待线程终止
这几个方法是我认为较为常用的方法,当然还有更多的方法,大家可以参考api.
curentThread()方法和getId及getName
class CreateDemo05 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取线程的名字使用getName方法,因为这里是实现Runnable接口,所以无法直接使用getName方法
//直接继承Thread类的话可以直接使用getName和getId方法
System.out.println("name:" + Thread.currentThread().getName() + "---run:" + i);
}
}
}
public class ThreadDemo05 {
public static void main(String[] args) {
CreateDemo05 createDemo05 = new CreateDemo05();
//实现Runnable接口需要使用到Thread类来调用start方法
Thread thread = new Thread(createDemo05);
//这里使用了setName来自定义线程的名字
thread.setName("ThreadName");
thread.start();
}
}
sleep()方法
需要注意的是sleep()在run方法中无法直接抛出异常,需要try…catch来捕捉异常
class CreateDemo04 extends Thread {
public void run() {
for (int i = 0; i < 10; i++) {
try {
//sleep里面的参数是毫秒值,代表休眠多少毫秒,这里设置为1秒
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i:" + i);
}
}
}
public class ThreadDemo04 {
public static void main(String[] args) {
System.out.println("main方法执行");
CreateDemo04 createDemo04 = new CreateDemo04();
createDemo04.start();
System.out.println("main方法创建子线程");
}
}
多线程运行状态
1.新建状态,指线程刚刚创建的时候,还没有调用start方法的时候
如:new Thread() 这时候线程还没开始执行,就是新建状态
2.就绪状态,线程调用了start()方法,已启动了线程,并调度了run()方法,当start方法返回后,
现在就处于就绪状态,注意并不是立即就运行的,因为需要等待cpu的调度,如果是单核cpu,
那么就会一个一个的线程去调度,所以可能有多个线程都是就绪状态.
3.运行状态,当cpu调度了线程后,就属于运行状态 真正的开始了执行run()方法
4.阻塞状态,通过调用sleep()方法,或者在I/O被阻塞的操作,锁被其它线程持有,等待触发条件.
这四种状态下的线程属于阻塞状态
5.死亡状态,run()方法正常执行完毕,线程会属于死亡状态,
或者一个未捕捉的异常终止了run方法运行
可以使用isAlive来判断是否死亡,如果是可运行状态或阻塞状态,方法返回true; 如果线程是new状态并且不可运行或线程死亡,则返回false.
下一篇介绍多线程的其他详细内容,如有错误,希望大佬指出,谢谢