实现线程的两种方式:
第一种:
/**
* 多线程
* 1、进程是一个应用程序
* 线程是一个进程中的执行场景/执行单元
* 一个进程可以启动多个线程
* 2、进程A和进程B的内存独立不共享
* 线程A和线程B,堆内存和方法区(.class文件)内存共享,栈内存独立,一个线程一个栈(栈与栈之间互不干扰,称为多线程并发)。
* JVM中方法区和堆只有一块,栈(调用方法)可以有多块
* 3、实现线程有两种方式:
* 第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法。
* 第二种方式:编写一个类,实现java.lang.Runnable接口,实现run方法。*常用
*/
public class JC {
public static void main(String[] args) {
//这里是main方法,在主线程中运行
MyThread myThread = new MyThread(); //新创建线程对象
/**
* 启动线程
* start()方法的作用是启动一个分支线程,在JVM中开辟一个新的栈空间,开辟完之后,这段代码瞬间结束。
* 启动成功的线程会自动调用run方法,且run方法在分支栈的栈底部(入栈),
* run方法和main方法分别在分支栈的栈底部、主栈的栈底部。run和main是平级的。
*
* 若这里不启动线程,直接MyTread.run()调用run方法,则没有创建出分支栈,run只是一个普通方法,
* 需要等run方法完全执行完之后,才会执行下面的循环。
*/
myThread.start();//瞬间结束,但是这行代码不结束,下面的代码不会执行(自上而下依次逐行)
//这里代码运行在主线程中
for (int i = 0; i < 100; i++) {
System.out.println("主线程:"+ i);
}
}
}
//重写run()方法
class MyThread extends Thread{
@Override
public void run() {
//这里代码运行在分支线程中
for (int i = 0; i < 100; i++) {
System.out.println("分支线程:"+ i);
}
}
}
第二种:
//编写一个类,实现Runnable接口
public class JB {
public static void main(String[] args) {
//创建可运行类的对象
//MyRunnable myRunnable = new MyRunnable();
//将可运行类的对象封装成一个线程对象
//Thread thread = new Thread(myRunnable);
//以上代码合并
Thread thread = new Thread(new MyRunnable());
//启动线程
thread.start();
for (int i = 0; i < 100; i++) {
System.out.println("主线程:"+ i);
}
}
}
//这里不是一个线程类,是一个可运行的类。
class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("分支线程:"+ i);
}
}
}
基本操作:
/**
* 线程基本操作1:
* 1、获取线程对象名字
* String name = 线程对象.getName();
* 2、修改线程对象名字
* 线程对象.setName();
* 3、获取当前线程
* Thread t = Thread.currentThread();
* 返回值t就是当前线程
*/
public class ThreadTest01 {
public static void main(String[] args) {
//获取当前线程
//这里出现在main线程中,所以获取的是main线程
Thread currentThread = Thread.currentThread();
System.out.println(currentThread.getName());
MyThread1 myThread = new MyThread1();
//设置线程名字
myThread.setName("线程B");
//获取线程名字
System.out.println(myThread.getName());
myThread.start();
}
}
class MyThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("分支线程:"+ i );
}
}
}
sleep方法:
/**
* 线程的sleep()方法:
* 1、静态方法:Thread.sleep(毫秒);
* 2、参数为毫秒
* 3、作用是让当前线程进入"阻塞状态"。
*/
public class ThreadTest02 {
public static void main(String[] args) {
MyThread2 m = new MyThread2();
m.setName("分支线程1");
m.start();
try {
//让当前线程睡眠10s
Thread.sleep(1000*10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//10s之后执行此行代码
System.out.println("nihao!");
}
}
class MyThread2 extends Thread{
@Override
public void run() {
//倒计时10s
for (int i = 10; i > -1 ; i--) {
System.out.println(Thread.currentThread().getName()+"---"+ i );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
终断线程睡眠:
/**
* 终断线程的睡眠
* 线程对象名.interrupt()
* 此方法是终止线程的睡眠,不是终断线程的执行
*/
public class ThreadTesst03 {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable1());
t.setName("A");
t.start();
//5s后终断线程A
try {
Thread.sleep(1000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//此行代码是终断线程A的睡眠(此终断机制依靠java异常处理机制)
t.interrupt();
}
}
class MyRunnable1 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"---begin");
try {
//睡眠一天
Thread.sleep(1000 * 60 * 60 *24);
} catch (InterruptedException e) {
e.printStackTrace();
}
//一天后执行到此处
System.out.println(Thread.currentThread().getName()+ "---end");
}
}
终止线程执行:
/**
* 合理终止一个线程的执行
*/
public class ThreadTest04 {
public static void main(String[] args) {
MyRunnable3 r = new MyRunnable3();
Thread t = new Thread(r);
t.setName("T");
t.start();
//模拟10s
try {
Thread.sleep(1000 * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//10s后将标记修改为false,终止线程
r.run = false;
}
}
class MyRunnable3 implements Runnable{
//打一个boolean标记
boolean run = true;
public void run(){
for (int i = 0; i < 20; i++) {
if(run){
System.out.println(Thread.currentThread().getName()+ "---" + i );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
//run=false时,终止线程
return;
}
}
}
}