(1)继承Thread类
/**
* 注:
* 1.需要覆写Thread类中的run()方法
* 2.启动线程要依靠Thread类中的start()方法,线程启动后会默认调用run()方法
*/
public class MyThread extends Thread{
private String title;
public MyThread(String title){
this.title=title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public void run(){
System.out.println(this.title+"继承Thread类实现多线程");
}
}
public class Main {
public static void main (String[] args){
MyThread t1 = new MyThread("线程1");
MyThread t2 = new MyThread("线程2");
MyThread t3 = new MyThread("线程3");
t1.start();
t2.start();
t3.start();
}
}
(2)实现Runnable接口
/**
* 注:
* 1.实现了Runnable接口的类将不再提供start()方法,所以为了继续使用Thread类启动多线程,可以利用Thread类中的构造方法对线程对象进行包裹
* 2.Thread类也是Runnable接口的子类。Thread类负责资源调度,实现Runnable的类负责处理真实业务
*/
public class MyThreadRunnable implements Runnable {
private String title;
public MyThreadRunnable(String title){
this.title=title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public void run(){
System.out.println("实现Runnable实现的多线程:"+this.title);
}
}
public class Main {
public static void main (String[] args){
MyThreadRunnable t1 = new MyThreadRunnable("线程1");
Thread thread1 = new Thread(t1);
MyThreadRunnable t2 = new MyThreadRunnable("线程2");
Thread thread2 = new Thread(t2);
MyThreadRunnable t3 = new MyThreadRunnable("线程3");
Thread thread3 = new Thread(t3);
thread1.start();
thread2.start();
thread3.start();
}
}
(3)实现Callable接口
Java针对多线程执行完毕后不能返回信息的缺陷,提供了Callable接口
/**
* 注:
* 1.需要通过java.util.concurrent.FutureTask类实现Callable接口与Thread类之间的联系
* 2.Callable接口泛型的值为call()方法的返回值类型
*/
public class MyThreadCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("实现Callabe接口的多线程");
return "返回值";
}
}
public class Main {
public static void main (String[] args){
MyThreadCallable t1 = new MyThreadCallable();
FutureTask<String> task1 = new FutureTask<>(t1);
Thread thread1 = new Thread(task1);
thread1.start();
}
}
(1)创建态
线程已经有了相应的内存空间和其他资源,但是处于不可运行的状态
对应语句:Thread 现成对象 = new Thread();
(2)就绪态
线程已经有了除了CPU的一切所需资源,在就绪队列中等待运行
对应语句:调用start()方法后,线程时处于就绪态
(3)运行态
线程在CPU上运行
对应语句:调用run()方法后,线程处于运行态
(4)阻塞态
一个正在运行的线程在某些特殊的情况下,将让出CPU并暂时中止自己的运行,进入阻塞状态
对应语句:如调用sleep()、suspend()、wait()等方法
(5)终止状态
当线程体中的run方法运行结束后,线程即处于终止状态,处于终止状态的线程不具有继续运行的能力
(1)多线程的命名和取得
注:如果没有设置线程名称,系统会自动为其分配一个名称,名称的形式以“Thread-xxx”的方式出现
(2)线程休眠
注:在进行休眠的时候有可能会产生中断异常InterruptedException,程序中必须强制性进行该异常的捕获与处理
(3)线程中断
注:线程的中断是被动完成的,每当被中断执行后就会产生InterruptedException异常
(4)线程强制执行
(5)线程礼让
在Java的线程操作中,所有的线程在运行前都会保持在就绪状态,那么此时会根据线程的优先级进行资源调度
线程同步是指若干个线程对象并行进行资源访问时实现的资源处理的保护操作
(1)同步代码块实现线程同步
同步代码块指使用 synchronized关键字定义的代码块,在该代码块执行时往往需要设置一个同步对象,由于线程操作的不确定状态,所以这个时候的同步对象可以选择this
public class Ticket implements Runnable{
//总票数10
private int ticket = 10;
@Override
public void run() {
while(true){
//同步代码块
synchronized (this){
if(this.ticket > 0){
try{
//模拟网络延迟
Thread.sleep(50);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖票,ticket=" + this.ticket--);
}else{
System.out.println("票已经卖光了");
break;
}
}
}
}
}
public class Demo {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket,"线程1").start();
new Thread(ticket,"线程2").start();
new Thread(ticket,"线程3").start();
}
}
(2)同步方法实现线程同步
同步代码块可以直接定义在某个方法中,使得方法中的操作进行同步处理,在方法声明上使用synchronized关键字即可
Java中的线程分为两类:用户线程和守护线程。守护线程是一种运行在后台的线程服务线程,当用户线程存在时,守护线程也可以同时存在,当用户线程全部消失时守护线程也会消失
注:用户线程和守护线程除了运行模式的区别外,其他完全相同
在多线程编程中,若干个线程为了可以实现公共资源的操作,往往是复制相应变量的副本,待操作完成后再将此副本变量数据与原始变量进行同步处理,如果需要直接进行原始变量操作可以在变量声明时使用volatile关键字