1.Thread多线程
1:程序:是一个静态的概念,具有特定功能的代码块
2:进程:是一个动态的概念,一个程序的一次运行对应一个进程
3:线程:是比进程更小的单位,一个进程可能有多条分支同时运行,其中的每一条分支就可以看作一个线程
多线程:一个进程由多个线程同时执行就是多线程
JVM 加载运行一个 publicstaticvoidmain(String[] args) {}方法时都会启动一个线程main,也叫主线程
2怎么创建一个线程
1:通过写一个类继承Thread类
重写Thread中的run()方法
调用线程的start()方法启动多线程
获取线程的线程名称
public class ThreadDemo extends Thread{
public ThreadDemo(String name) {
super(name);
}
public void run() {
for (int i = 0; i <1000; i++) {
System.out.println(this.getName()+i);
}
}
public static void main(String[] args) {
ThreadDemo demo =new ThreadDemo("myThread");
//demo.run(); 调用线程内的run方法是方法的调用,不是启动多线程
demo.start();//start()方法让线程就绪
MyRunnable demo2 =new MyRunnable();
new Thread(demo2,"MyRunnable").start();
for (int i = 0; i <1000; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
}
2:通过实现Runnable接口
实现Runnable接口里的run()方法
需要先创建实现Runnable接口类的实例
xxx r= new xxx();
在new Thread(r).start()方法 启动线程
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
public static void main(String[] args) {
MyRunnable demo =new MyRunnable();
new Thread(demo,"MyRunnable").start();
for (int i = 0; i <1000; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
}
2.给线程名称:
Thread或者Thread的子类方法中
用this.getName();
如果在不是Thread的子类中获取
Thread.currentThread().getName()
让线程类提供一个带参数的构造器
AThread extends Thread{
AThread(String name){
super(name)}
}
这样这个带参数的构造器就会给线程提供一个新的名字name
3.线程中常用的方法
satart()启动线程
run()线程要执行的代码,启动线程的前提是调用start()
一个线程start()操作系统会自动根据cpu调度任务运行run()
run()不能被程序直接调用,直接调用不是多线程
isAlive();判断线程是否处于激活状态
线程在start()之后run方法代码运行完成之前都是true,其他时候都是false
sleep(毫秒数)让当前线程睡眠指定的毫秒数,时间到了立即进入激活状态,不会释放所占用的资源
yield()暂停当前运行的线程,让当前线程让出cpu的使用权
join()合并线程
interrupt()中断线程
stop()停止线程
wait()
4.线程的同步
1:锁方法 在方法上加上 synchronized
让同一个时间只有一个线程可以访问该方法
public synchronized double drawMoney(double money) {
double result=0;
if (this.money>=money) {
this.money=this.money-money;
result=money;
System.out.println(Thread.currentThread().getName()+"取款成功!余额"+this.money);
}else {
System.out.println(Thread.currentThread().getName()+"取款失败!余额"+this.money+"不足"+money);
}
return result;
}
2:锁对象 在多线程操作同一个对象的时候,我们可以对对象加锁
让同一个时间只有一个线程可以访问该对象
package com.zt.synchronizedobject;
public class Account {
private String cardNum;
private double money;
public String getCardNum() {
return cardNum;
}
public void setCardNum(String cardNum) {
this.cardNum = cardNum;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public Account(String cardNum, double money) {
super();
this.cardNum = cardNum;
this.money = money;
}
@Override
public String toString() {
return "Account [cardNum=" + cardNum + ", money=" + money + "]";
}
}
public class AccountThread extends Thread {
Account account;
double money;
public AccountThread(Account coAccount,double money,String name) {
super(name);
this.account=coAccount;
this.money=money;
}
@Override
public void run() {
synchronized (account) {//锁对象
if (account.getMoney()>=money) {
account.setMoney(account.getMoney()-money);
System.out.println(Thread.currentThread().getName()+"取款"+money+"成功!余额"+account.getMoney());
}else {
System.out.println(Thread.currentThread().getName()+"取款失败!余额"+account.getMoney()+"不足"+money);
}
}
}
public static void main(String[] args) {
Account account =new Account("1212131312",10000);
AccountThread t1=new AccountThread(account,3000,"张三");
AccountThread t2=new AccountThread(account,3666,"毛毛");
AccountThread t3=new AccountThread(account,3000,"唐唐");
t1.start();
t2.start();
t3.start();
}
}
3:锁机制
java.util.concurrent.locks.ReentrantLock
互斥锁 lock() 获取锁
unlock() 解锁 试图释放此锁
public class Account {
private String cardNum;
private double money;
ReentrantLock lock =new ReentrantLock();//创建锁对象
public double drawMoney(double money) {
double result=0;
lock.lock();//上锁
if (this.money>=money) {
this.money=this.money-money;
result=money;
System.out.println(Thread.currentThread().getName()+"取款成功!余额"+this.money);
}else {
System.out.println(Thread.currentThread().getName()+"取款失败!余额"+this.money+"不足"+money);
}
lock.unlock();//解锁
return result;
}
eg:模拟卖票系统:
package com.zt;
import java.util.Date;
public class Ticket {
private String startCity;
private String endCity;
private double money;
private Date startTime;
private int Maxnum;
public Ticket(String startCity, String endCity, double money ,int Maxnum) {
this.startCity = startCity;
this.endCity = endCity;
this.money = money;
this.Maxnum=Maxnum;
}
public synchronized Ticket saleTicket() {
Ticket t =null;
if (Maxnum>0) {
t= new Ticket(startCity,endCity, money,Maxnum);
Maxnum--;
}
return t;
}
@Override
public String toString() {
return "Ticket [startCity=" + startCity + ", endCity=" + endCity
+ ", money=" + money + ", startTime=" + startTime + ", Maxnum="
+ Maxnum + "]";
}
}
package com.zt;
public class TicketThread extends Thread{
Ticket ticket;
public TicketThread( Ticket ticket,String name){
super(name);this.ticket=ticket;
}
@Override
public void run() {
for (int i = 0; i < 500; i++) {
Ticket obj=ticket.saleTicket();
System.out.println(this.getName()+"卖出了第"+(i+1)+"张");
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Ticket ticket=new Ticket("南昌站", "北京站", 315, 500);
TicketThread thread =new TicketThread(ticket,"南昌站");
TicketThread thread2 =new TicketThread(ticket,"北京站");
thread.start();
thread2.start();
}
}