线程基础
- 进程和线程
- 进程
- 线程
- 多线程
- 线程的创建
- 第一种创建方式
- 第二种创建方式
- 综合两种方式使用匿名内部类的方式创建进程
- 获取当前线程
- 线程信息的常见API
进程和线程
进程
每个独立执行的程序都可以被为一个进程,也就是正在执行的程序(是由操作系统操控的)
真正负责执行代码的硬件是CPU,同一时刻CPU只能干一件事
系统可以为每一个进程一段有限的使用CPU的时间,也可以称之为CPU时间片
线程
线程是进程中的任务执行序列
线程就是一个正在运行的进程中的一个任务
多线程
一个进程中可以同时包含多个线程,每个线程可以得到一小段的执行时间
一个进程中某个时间段内同时并发的多个任务执行序列就叫做多线程
注:线程不能独立存在,必须依附于进程
线程的创建
第一种创建方式
继承Threadl类,重写run()方法,启动时调用start()方法
package com.tedu.thread;
/**
* 线程由两种创建方式
* 第一种
* 编写了一个继承了java.lang.Thread子类
*
* 多线程本质上改变了代码的执行方式
* 由一句句执行,改变成了多线程并发执行
* 并发执行不是真正意义上的同时执行,只是利用了CPU的
*
* @author Wildmess
*
*/
public class ThreadDemo {
public static void main(String[] args) {
/*
* 开启线程
* 线程实例化Thread类的对象
*/
MyThread1 t1 = new MyThread1();
MyThread2 t2 = new MyThread2();
/*
* 使用Thread类对象的start方法开始新线程
* 我们重写的是run方法,但是我们不能直接调用它,要通过start来执行
*/
t1.start();
t2.start();
}
}
class MyThread1 extends Thread{
/*
* 要想开启一个新线程,必须在继承Thread类之后
* 重写父类中的run方法
*/
@Override
public void run() {
/*
* run方法中的代码就是开启新线程要执行的任务序列
*/
for(int i=0; i<1000; i++) {
System.out.println("Who are you?");
}
}
}
class MyThread2 extends Thread{
@Override
public void run() {
for(int i=0; i<1000; i++) {
System.out.println("I an Tom.");
}
}
}
优点:
代码简单,适合写匿名内部类的形式
缺点:
java代码单继承,一旦继承了Thread类就不能继承其他类了
这种创建方式将这个线程能做什么直接固定了,不能修改,增加了程序的耦合性,不利于线程重用
第二种创建方式
显现Rannable接口,重写run()方法,启动时调用start()方法
package com.tedu.thread;
/**
* 实现Runnable接口实现
* @author Wildmess
*
*/
public class ThreadDemo2 {
public static void main(String[] args) {
//实例化任务
Runnable r1 = new MyRunnable1();
Runnable r2 = new MyRunnable2();
//创建了俩个线程,并且指定相应的任务
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
class MyRunnable1 implements Runnable{
@Override
public void run() {
for(int i=0; i<1000; i++){
System.out.println("Who are you?");
}
}
}
class MyRunnable2 implements Runnable{
@Override
public void run() {
for(int i=0; i<1000; i++){
System.out.println("I an Tom.");
}
}
}
优点:
任务和线程对象分离,耦合度低
缺点:
需要额外的代码实例化任务对象,代码比较多
不需要继承Thread类,所以有些方法不能直接使用
综合两种方式使用匿名内部类的方式创建进程
package com.tedu.thread;
public class ThreadDemo3 extends Thread implements Runnable {
public static void main(String[] args) {
//方式一
Thread t1 = new Thread() {
@Override
public void run() {
for(int i = 0; i< 1000; i++) {
System.out.println("Who are you?");
}
}
};
//方式二
Runnable r2 = new Runnable() {
@Override
public void run() {
for(int i = 0; i< 1000; i++) {
System.out.println("I an Tom.");
}
}
};
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
获取当前线程
static Thread current Thread()
获取当前线程的对象,可从对象中获得一些当前线程的信息
package com.tedu.thread;
public class CurrentThreadDemo {
public static void main(String[] args) {
/*
* main方法实际上也是一个线程
* 只是不由程序员创建
*/
Thread m =Thread.currentThread();//获取当前代码运行的线程,返回的是当前线程对象
System.out.println(m);
Thread t = new Thread() {
@Override
public void run() {
dosome();
}
};
t.setName("线程一");//可以对特定线程进行更名
t.start();
}
public static void dosome() {
Thread t = Thread.currentThread();
System.out.println(t);
}
}
线程信息的常见API
一个线程都有什么信息可以获得呢?下面列出了一些常见线程的线程信息API
package com.tedu.thread;
/**
* 获取线程的相关信息方法
* @author Wildmess
*
*/
public class ThreadInfoDemo {
public static void main(String[] args) {
//获取主线程
Thread main = Thread.currentThread();
System.out.println(main);
//获取线程的唯一标识
long id = main.getId();
System.out.println("线程的唯一标识:" + id);
//获取线程的名字
String name = main.getName();
System.out.println("线程名称:" + name);
main.setName("我改名了!");
System.out.println("线程名称:" + main.getName());
//获取线程的优先级,是一个1-10之间的整数
//默认是5,1表示优先级最低,10表示优先级最高
int priority = main.getPriority();
System.out.println("优先级:" + priority);
//线程是否处于活动状态
boolean isAlive = main.isAlive();
System.out.println("线程是否活着:" + isAlive);
//线程是否为守护线程
boolean isDaemon = main.isDaemon();
System.out.println("线程是否为守护线程:" + isDaemon);
//线程是否被中断
//线程有可能非正常中断
boolean isInterrupted = main.isInterrupted();
System.out.println("线程是否被中断:" + isInterrupted);
}
}
共有条评论 网友评论