创建线程
定义+创建+启动
- 创建线程的第一种方式:继承Thread类
public class Test{
public static void main(String[] args){
Thread thread=new Process();
thread.start();
for(int i=0;i<3;i++)
System.out.println("ooo");
}
}
class Process extends Thread{
public void run()
{
for(int i=0;i<5;i++)
System.out.println("haha");
}
}
2. 创建线程的第二种方式:实现Runnable接口
public class Test{
public static void main(String[] args){
Thread thread=new Thread(new Process());
thread.start();
for(int i=0;i<3;i++)
System.out.println("ooo");
}
}
class Process implements Runnable{
public void run(){
for(int i=0;i<5;i++)
System.out.println("haha");
}
}
线程命名
public class Test{
public static void main(String[] args){
Thread thread=new Thread(new Process());
thread.start();
//获取主线程对象
Thread mThread=Thread.currentThread();
//获取主线程名称
System.out.println(mThread.getName());
//给线程命名
mThread.setName("main");
System.out.println(Thread.currentThread().getName());
}
}
class Process implements Runnable{
public void run(){
Thread t=Thread.currentThread();
System.out.println(t.getName());
t.setName("t1");
System.out.println(Thread.currentThread().getName());
}
}
线程优先级
//优先级高的线程获得的时间片相对多一些
//优先级:1-10 最高:10 最低:1 默认:5
public class Test{
public static void main(String[] args){
Thread t1=new Thread(new Process());
Thread t2=new Thread(new Process());
//获取线程优先级
System.out.println(t1.getPriority());
System.out.println(t2.getPriority());
t1.setName("t1");
t2.setName("t2");
//设置线程优先级
t1.setPriority(1);
t2.setPriority(10);
//启动线程
t1.start();
t2.start();
}
}
class Process implements Runnable{
public void run(){
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}
线程休眠
腾出CPU给其他的线程
1、
public class Test{
public static void main(String[] args){
Thread t1=new Thread(new Process());
t1.start();
}
}
class Process implements Runnable{
public void run(){
for(int i=0;i<5;i++)
{
System.out.println(Thread.currentThread().getName()+"--->"+i);
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
public class Test{
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(new Process());
t1.setName("t1");
t1.start();
for(int i=0;i<20;i++)
{
System.out.println(Thread.currentThread().getName()+"--->"+i);
Thread.sleep(500);//阻塞的是当前线程
}
}
}//main方法可以抛出异常
class Process implements Runnable{
public void run(){
for(int i=0;i<5;i++)
{
System.out.println(Thread.currentThread().getName()+"--->"+i);
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}//run方法为重写Thread类中的run方法,Thread类中的run方法不抛出异常,因此重写的方法不能抛出更多的异常
}
public class Test{
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(new Process());
t1.setName("t1");
t1.start();
t1.sleep(5000);//相当于Thread.sleep(5000);
System.out.println("Hello world!");
}
}
class Process implements Runnable{
public void run(){
for(int i=0;i<10;i++)
{
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
System.out.println("线程结束");
}
}
2、
//线程正在休眠,打断其休眠
public class Test{
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(new Process());
t1.setName("t1");
t1.start();
Thread.sleep(5000);
t1.interrupt();//是通过抛出InterruptedException异常来实现的,try...catch语句结束
}
}//main方法可以抛出异常
class Process implements Runnable{
public void run(){
try{
Thread.sleep(10000);
}catch(InterruptedException e){
e.printStackTrace();
}
for(int i=0;i<5;i++)
System.out.println(Thread.currentThread().getName()+"--->"+i);
}//run方法为重写Thread类中的run方法,Thread类中的run方法不抛出异常,因此重写的方法不能抛出更多的异常
}
3、
//如何正确的更好的终止一个正在执行的线程
public class Test{
public static void main(String[] args) throws InterruptedException {
Process process =new Process();
Thread t1=new Thread(process);
t1.setName("t1");
t1.start();
Thread.sleep(5000);
process.run=false;
}
}
class Process implements Runnable{
boolean run=true;
public void run(){
for(int i=0;i<1000;i++)
{
if(run)
{
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}
System.out.println("线程结束");
}
}
线程合并
合并后变为单线程,只能一个线程执行完后,另一个线程才能执行
public class Test{
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(new Process());
t1.setName("t1");
t1.start();
t1.join();
for(int i=0;i<20;i++)
{
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}
}
class Process implements Runnable{
public void run(){
for(int i=0;i<5;i++)
{
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}
}
线程同步:为了保证共享数据的安全
//演示不使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作
public class Test{
public static void main(String[] args) {
Account account =new Account("Jack", 5000.0);
Process process =new Process(account);
Thread t1=new Thread(process);
Thread t2=new Thread(process);
t1.start();
t2.start();
}
}
class Account{
private String name;
private double yukuan;
Account(String name,double yukuan){
this.name=name;
this.yukuan=yukuan;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getYukuan() {
return yukuan;
}
public void setYukuan(double yukuan) {
this.yukuan = yukuan;
}
//对外提供取款操作
public void delete(double money) throws InterruptedException
{
double after=this.yukuan-money;
Thread.sleep(1000);
this.yukuan=after;
System.out.println("取款成功,剩余额为"+this.yukuan);
}
}
class Process implements Runnable{
Account account ;
Process(Account account)
{
this.account=account;
}
public void run(){
try{account.delete(1000.0);}
catch(InterruptedException e){
e.printStackTrace();
}
}
}
double after=this.yukuan-money;
Thread.sleep(1000);
this.yukuan=after;
System.out.println("取款成功,剩余额为"+this.yukuan);
同一时间只能有一个线程执行上述代码。将需要同步的代码放到synchronized(共享对象){…}中,构成同步语句块
//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
public static void main(String[] args) {
Account account =new Account("Jack", 5000.0);
Process process =new Process(account);
Thread t1=new Thread(process);
Thread t2=new Thread(process);
t1.start();
t2.start();
}
}
class Account{
private String name;
private double yukuan;
Account(String name,double yukuan){
this.name=name;
this.yukuan=yukuan;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getYukuan() {
return yukuan;
}
public void setYukuan(double yukuan) {
this.yukuan = yukuan;
}
//对外提供取款操作
public void delete(double money) throws InterruptedException
{
//变为单线程
synchronized (this) {
double after=this.yukuan-money;
Thread.sleep(1000);
this.yukuan=after;
System.out.println("取款成功,剩余额为"+this.yukuan);
}
}
}
class Process implements Runnable{
Account account ;
Process(Account account)
{
this.account=account;
}
public void run(){
try{account.delete(1000.0);}
catch(InterruptedException e){
e.printStackTrace();
}
}
}
发现代码的执行时间增长,代码的执行效率降低,但是数据的安全性得到了保证
原理: t1线程执行到同步语句块,遇到了synchronized关键字,就会去找synchronized(共享对象)内共享对象的对象锁,如果找到,则进入同步语句块执行程序,当同步语句块中的代码执行结束之后,t1线程归还共享对象的对象锁;在t1线程执行同步语句块的过程中,如果t2线程也过来执行同步语句块,就也要去找共享对象的对象锁,但是该对象锁被t1线程持有,所以t2线程只能等待t1线程执行完归还对象锁后才去执行同步语句块
在java中任何一个对象都有对象锁,即每一个对象都有0、1标志
第二种线程同步的方式
//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
public static void main(String[] args) {
Account account =new Account("Jack", 5000.0);
Process process =new Process(account);
Thread t1=new Thread(process);
Thread t2=new Thread(process);
t1.start();
t2.start();
}
}
class Account{
private String name;
private double yukuan;
Account(String name,double yukuan){
this.name=name;
this.yukuan=yukuan;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getYukuan() {
return yukuan;
}
public void setYukuan(double yukuan) {
this.yukuan = yukuan;
}
//对外提供取款操作
public synchronized void delete(double money) throws InterruptedException
{
double after=this.yukuan-money;
Thread.sleep(1000);
this.yukuan=after;
System.out.println("取款成功,剩余额为"+this.yukuan);
}
}
class Process implements Runnable{
Account account ;
Process(Account account)
{
this.account=account;
}
public void run(){
try{account.delete(1000.0);}
catch(InterruptedException e){
e.printStackTrace();
}
}
}
synchronized关键字加到成员方法上
其实还是去找当前对象this的对象锁
一般采用第一种方式,第二种方式用于成员方法中所有的代码都需要同步的情况,此时程序的执行效率可能十分低下
StringBuffer、Vector、HashTabel类内含synchronized,因此它们都是线程安全的
遇synchronized就去找锁,找得到就去执行,找不到就等
//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
public static void main(String[] args) throws InterruptedException{
Account account =new Account();
Process process =new Process(account);
Thread t1=new Thread(process);
Thread t2=new Thread(process);
t1.setName("t1");
t2.setName("t2");
t1.start();
//若想让m1方法先执行,可以添加延迟
Thread.sleep(1000);
t2.start();
}
}
class Account{
public synchronized void m1() throws InterruptedException
{
Thread.sleep(2000);
System.out.println("m1 is doing...");
}
//m2没有synchronized,不会去找对象锁,不是线程同步,不会等m1
public void m2(){
System.out.println("m2 is doing...");
}
}
class Process implements Runnable{
Account account ;
Process(Account account)
{
this.account=account;
}
public void run(){
if(Thread.currentThread().getName()=="t1")
{
try{
account.m1();
}catch(InterruptedException e)
{
e.printStackTrace();
}
}
else if(Thread.currentThread().getName()=="t2")
account.m2();
}
}
//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
public static void main(String[] args) throws InterruptedException{
Account account =new Account();
Process process =new Process(account);
Thread t1=new Thread(process);
Thread t2=new Thread(process);
t1.setName("t1");
t2.setName("t2");
t1.start();
//若想让m1方法先执行,可以添加延迟
Thread.sleep(1000);
t2.start();
}
}
class Account{
public synchronized void m1() throws InterruptedException
{
Thread.sleep(2000);
System.out.println("m1 is doing...");
}
//m2有synchronized,就会去找对象锁,而对象又是共享的,是线程同步,m2会等m1
public synchronized void m2(){
System.out.println("m2 is doing...");
}
}
class Process implements Runnable{
Account account ;
Process(Account account)
{
this.account=account;
}
public void run(){
if(Thread.currentThread().getName()=="t1")
{
try{
account.m1();
}catch(InterruptedException e)
{
e.printStackTrace();
}
}
else if(Thread.currentThread().getName()=="t2")
account.m2();
}
}
//演示使用线程同步机制的取款例子,多线程同时对同一个账户进行取款操作,使用线程同步机制保证数据安全
public class Test{
public static void main(String[] args) throws InterruptedException{
Account account1 =new Account();
Account account2 =new Account();
Process process1 =new Process(account1);
Process process2 =new Process(account2);
Thread t1=new Thread(process1);
Thread t2=new Thread(process2);
//都没有共享对象,不是线程同步,m2不会等m1
t1.setName("t1");
t2.setName("t2");
t1.start();
//若想让m1方法先执行,可以添加延迟
Thread.sleep(1000);
t2.start();
}
}
class Account{
public synchronized void m1() throws InterruptedException
{
Thread.sleep(2000);
System.out.println("m1 is doing...");
}
public synchronized void m2(){
System.out.println("m2 is doing...");
}
}
class Process implements Runnable{
Account account ;
Process(Account account)
{
this.account=account;
}
public void run(){
if(Thread.currentThread().getName()=="t1")
{
try{
account.m1();
}catch(InterruptedException e)
{
e.printStackTrace();
}
}
else if(Thread.currentThread().getName()=="t2")
account.m2();
}
}
类锁:锁是类级别的,只有一个
在静态方法上添加synchronized关键字
public class Test{
public static void main(String[] args) throws InterruptedException{
Process process =new Process();
Thread t1=new Thread(process);
Thread t2=new Thread(process);
t1.setName("t1");
t2.setName("t2");
t1.start();
Thread.sleep(1000);
t2.start();
}
}
class Process implements Runnable{
public void run()
{
if(Thread.currentThread().getName()=="t1")
{
try{
Myclass.m1();
}catch(Exception e)
{
e.printStackTrace();
}
}
else if(Thread.currentThread().getName()=="t2")
Myclass.m2();
}
}
class Myclass{
public synchronized static void m1() throws Exception
{
Thread.sleep(2000);
System.out.println("m1 is doing...");
}
public static void m2(){
System.out.println("m2 is doing...");
}//m2没有synchronized修饰,不会去找类锁,所以m2不会去等m1
}
public class Test{
public static void main(String[] args) throws InterruptedException{
Process process =new Process();
Thread t1=new Thread(process);
Thread t2=new Thread(process);
t1.setName("t1");
t2.setName("t2");
t1.start();
Thread.sleep(1000);
t2.start();
}
}
class Process implements Runnable{
public void run()
{
if(Thread.currentThread().getName()=="t1")
{
try{
Myclass.m1();
}catch(Exception e)
{
e.printStackTrace();
}
}
else if(Thread.currentThread().getName()=="t2")
Myclass.m2();
}
}
class Myclass{
public synchronized static void m1() throws Exception
{
Thread.sleep(2000);
System.out.println("m1 is doing...");
}
public synchronized static void m2(){
System.out.println("m2 is doing...");
}//m2有synchronized修饰,会去找类锁,所以m2会等m1
}
public class Test{
public static void main(String[] args) throws InterruptedException{
//不同对象
Myclass myclass =new Myclass();
Myclass myclass2 =new Myclass();
Process process =new Process(myclass);
Process process2 =new Process(myclass2);
Thread t1=new Thread(process);
Thread t2=new Thread(process2);
//类锁,与对象无关,所以m2会去等m1
t1.setName("t1");
t2.setName("t2");
t1.start();
Thread.sleep(1000);
t2.start();
}
}
class Process implements Runnable{
Myclass myclass;
Process(Myclass myclass)
{
this.myclass=myclass;
}
public void run()
{
if(Thread.currentThread().getName()=="t1")
{
try{
Myclass.m1();
}catch(Exception e)
{
e.printStackTrace();
}
}
else if(Thread.currentThread().getName()=="t2")
Myclass.m2();
}
}
class Myclass{
public synchronized static void m1() throws Exception
{
Thread.sleep(2000);
System.out.println("m1 is doing...");
}
public synchronized static void m2(){
System.out.println("m2 is doing...");
}
}
死锁:前提还是共享,有两个共享对象
t1线程已经锁了o1,还要去锁o2;而t2线程已经锁了o2,还要去锁o1
t1、t2线程都不能执行完去释放各自拥有的锁,陷入僵持局面
public class Test{
public static void main(String[] args) throws InterruptedException{
Object o1=new Object();
Object o2=new Object();
//两个线程共享对象,如果都不是同一个对象的话怎么会造成死锁呢
Thread t1=new Thread(new Process(o1,o2));
Thread t2=new Thread(new Process2(o1,o2));
t1.start();
t2.start();
}
}
//两个线程所执行的run方法操作不同,所以可以写两个线程类
class Process implements Runnable{
Object o1;
Object o2;
Process(Object o1,Object o2)
{
this.o1=o1;
this.o2=o2;
}
public void run()
{
synchronized(o1){
System.out.println("我已将o1上锁,我还想去锁o2");
try{
Thread.sleep(2000);
}catch(InterruptedException e)
{
e.printStackTrace();
}
synchronized(o2){
}
}
}
}
class Process2 implements Runnable{
Object o1;
Object o2;
Process2(Object o1,Object o2)
{
this.o1=o1;
this.o2=o2;
}
public void run(){
synchronized(o2){
System.out.println("我已将o2上锁,我还想去锁o1");
try{
Thread.sleep(2000);
}catch(InterruptedException e)
{
e.printStackTrace();
}
synchronized(o1){
}
}
}
}
总结: 线程同步靠的就是锁,而线程同步的前提是 共享 类或对象,这点很重要
守护线程
线程可分为用户线程和守护线程,守护线程在所有用户线程都结束后才能结束,如java的垃圾回收器就是一个守护线程,在应用程序的所有线程都结束后才能结束
JVM会自动启动一个主线程和垃圾回收器(守护线程)
守护线程一般都是无限执行的,在所有用户线程结束后自动结束
public class Test{
public static void main(String[] args) throws InterruptedException{
Thread t1=new Thread(new Process());
t1.setName("t1");
t1.start();
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+"--->"+i);
//此时t1为用户线程,会一直进行,主线程结束后t1也会继续执行
}
}
class Process implements Runnable{
public void run(){
int i=0;
while(true)
{
System.out.println(Thread.currentThread().getName()+"--->"+i);
i++;
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
public class Test{
public static void main(String[] args) throws InterruptedException{
Thread t1=new Thread(new Process());
t1.setName("t1");
t1.setDaemon(true);//设置为守护线程
t1.start();
for(int i=0;i<10;i++)
System.out.println(Thread.currentThread().getName()+"--->"+i);
//此时t1为守护线程,主线程结束后没有其他的用户线程了,t1会自动结束
}
}
class Process implements Runnable{
public void run(){
int i=0;
while(true)
{
System.out.println(Thread.currentThread().getName()+"--->"+i);
i++;
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
定时器Timer:每隔一段固定的时间执行一段固定的代码
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class Test{
public static void main(String[] args) throws Exception{
//创建定时器
Timer timer=new Timer();
//指定定时任务
timer.schedule(new LogTimerTask(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").parse("2020-09-06 16:50:00 000"),10*1000);
}
}
class LogTimerTask extends TimerTask{
public void run(){
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));
}
}
/*
* void schedule(TimerTask task,Date firstTime,long period):安排指定的任务在指定的时间开始进行重复的固定延迟执行,会抛出异常
*
* public abstract class TimerTask extends Object implements Runnable:TimerTask是一个抽象类,类内有run抽象方法
* abstract void run():此计时器任务要执行的操作
*
*/