线程是操作系统运算调度的最小单位
任务,多线程,进程
进程是一个程序的执行的过程,它是一个动态的概念,是系统资源分配的单位,里面有若干个线程
-
线程就是独立的执行路径
-
在程序运行时,即使没有自己创建线程,后台也会有多个线程,如:主线程,gc线程
-
main()称之为主线程,为系统入口,用于执行整个程
Thread class → 继承Thread(重点)
public class TestThread extends Thread{
@Override
public void run() {
System.out.println("54654");
}
public static void main(String[] args) {
TestThread testThread=new TestThread();
//调用start()方法开启多线程,交替执行,同时执行
testThread.start();
//先执行run方法在执行后面的输出
testThread.run();
System.out.println("78465154");
}
}
Runnable接口 → 实现Runnable接口(重点)
//创建线程方式2,实现Runable接口,重写run方法,执行线程需要丢入runable接口实现类,调用start方法
public class RunTest3 implements Runnable{
@Override
public void run() {
System.out.println("546");
}
public static void main(String[] args) {
RunTest3 runTest3=new RunTest3();
//创建线程对象,通过线程对象来开启线程,代理
Thread thread=new Thread(runTest3);
thread.start();
}
}
抢票问题
package XianChen;
public class TestThread4 implements Runnable{
private int ticket=10;
@Override
public void run() {
try {
Thread.sleep(200);//延时2s
} catch (InterruptedException e) {
e.printStackTrace();
}
while (ticket!=0){
System.out.println(Thread.currentThread().getName()+"拿到第"+ticket--+"票");
}
System.out.println("票以售空");
}
public static void main(String[] args) {
TestThread4 testThread4=new TestThread4();
new Thread(testThread4,"小明").start();
new Thread(testThread4,"小红").start();
new Thread(testThread4,"小光").start();
}
}
龟兔赛跑
public class TestThread5 implements Runnable {
private String winner;
public void run() {
for (int i = 0; i <= 100; i++) {//赛道距离为100
boolean flag=gameover(i);
if(flag)
{
break;
}
System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
}
}
public boolean gameover(int steps){
if(winner!=null) {//当胜利者存在时,两个线程的共同参数
return true;
}
else if(steps >= 100) {
winner = Thread.currentThread().getName();
System.out.println("胜利者是" + winner);
return true;
}
return false;
}
public static void main(String[] args) {
TestThread5 testThread5=new TestThread5();
new Thread(testThread5,"兔子").start();
new Thread(testThread5,"乌龟").start();
}
}
Callable接口 → 实现Callable接口(了解)
静态代理
-
真实对象和代理对象都要实现同一个接口
-
代理对象要代理真是角色
优点
代理对象可以做很多真实对象做不了的事情
例如: 你:真是对象
婚前公司:代理,帮你处理结婚的事情 相当于 Thread
结婚:两者都是实现结婚这件事,
Lamda表达式
public class lambda {
public static void main(String[] args) {
//lambda表达式
Wed wed2=(int a)->{
System.out.println("68746");
};
wed2.ol(7);
简化后
Wed wed2=(a)->System.out.println("68746");
}
优点
-
避免匿名内部类定义过多
-
可以让代码看起来更加简洁
-
去掉了一些没有意义的代码,只留下核心的逻辑
1,函数式接口,一个接口里面只包含一个抽象方法
public interface Runable{
void run();
}
线程停止
package XianChen;
//测试Stop
//建议线程正常停止--->利用次数,不建议死循环
//建议使用标志位---->设置一个标志位
//不要使用stop或者destroy等过时或者jdk不建议使用的方法
public class StopTest implements Runnable {
boolean flag=true;
int i=0;
@Override
public void run() {
while (flag){
System.out.println("result: "+i++);
}
}
public void stop(){
this.flag=false;
}
public static void main(String[] args) {
StopTest stopTest=new StopTest();
new Thread(stopTest).start();
for (int i = 0; i < 1000; i++) {
System.out.println("main"+i);
if(i==900){
stopTest.stop();
System.out.println("线程该停止了");
}
}
}
}
线程休眠sleep
-
sleep(时间)指当前线程阻塞的毫秒数
-
sleep存在异常InterruptException
-
sleep时间达到后线程进入就绪状态
-
sleep可以模拟网络延时,倒计时等
-
每一个对象都有一个锁,sleep不会释放锁
package XianChen;
import java.sql.DatabasemetaData;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SleepTest {
private int a=10;
public void sleep() throws InterruptedException{
while (a>=0){//倒计时
System.out.println(""+a--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SleepTest sleepTest = new SleepTest();
Date date=new Date(System.currentTimeMillis());//获取系统时间
while (true) {
try {
Thread.sleep(1000);//延时一秒
System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));//输出当前系统时间
date=new Date(System.currentTimeMillis());//更新当前时间赋值给date
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程礼让Yield
-
让当前正在执行的线程暂停,但不阻塞
-
将线程转换为就绪状态
-
让cpu重新调度,礼让不一定成功
观察状态
Thread.State state =Thread.getState(); System.out.pritn(state);
线程的优先级priority
程序先执行优先级高的
public class PriorityTast {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+" "+Thread.currentThread().getPriority());//主线程优先级
priority priority=new priority();
Thread t1=new Thread(priority);
Thread t2=new Thread(priority,"2");
Thread t3=new Thread(priority,"3");
//先设置优先级,在输出
t1.start();
t2.setPriority(4);//设置优先级
t2.start();
t3.setPriority(Thread.MAX_PRIORITY);
t3.start();
}
}
class priority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" "+Thread.currentThread().getPriority());
}
}
守护线程
线程分为用户线程和守护线程
虚拟机必须确保用户线程执行完毕
虚拟机不必等待守护线程执行完毕
package XianChen;
public class DaemonTast {
public static void main(String[] args) {
people people=new people();
God god=new God();
Thread t1=new Thread(god);
Thread t2=new Thread(people);
t1.setDaemon(true);//默认为false表示是用户线程,设置为true时为守护线程,正常的线程都为用户线程
t1.start();//守护线程启动
t2.start();//用户线程启动
}
}
class people implements Runnable{
@Override
public void run() {
int count=365;
while (count>=0)
{
count--;
System.out.println("you live happy");
}
System.out.println("everthing is over");
}
}
class God implements Runnable{
@Override
public void run() {
while (true)
{
System.out.println("protect you all the time");
}
}
}
线程同步
并发:一个对象被多个线程同时执行(列如:抢票)
形成条件:队列+锁(synchronized) 保证线程同步的安全性
存在问题
-
一个线程持有锁会导致其他所有需要此锁的线程挂起(排队上厕所 锁相当于门)
-
多个线程竞争下,会导致性能下降
-
一个优先级高的线程等待一个优先级低的线程释放锁,会导致优先级倒置,引起性能问题
同步方法和同步和代码块
synchronized方法和synchronized代码块
public synchronized void methon(){
}
synchronized(object){//对象为变量
}
//银行取钱
public class TicketTast {
public static void main(String[] args) {
Account account=new Account(100,"共同资金:");
bank you=new bank(account,50,"你");
bank people=new bank(account,100,"朋友");
you.start();//开启线程
people.start();
}
}
//账户
class Account {
int money;//余额
String name;//账户名
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行
class bank extends Thread {
Account account;
int drawingmoney;
int nowmoney;
String name;
public bank(Account account, int drawingmoney, String name) {
super(name);
this.account = account;
this.drawingmoney = drawingmoney;
}
@Override
public void run() {
synchronized (account) {//synchroized块对账户account进行锁定
System.out.println(account.name + account.money);
if (account.money - drawingmoney < 0) {
System.out.println(Thread.currentThread().getName() + "的余额不足,取不了");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//银行卡内余额=当前账号余额-取出来的钱
account.money = account.money - drawingmoney;
System.out.println(Thread.currentThread().getName() + " 取了钱目前卡内剩下余额:" + account.money);
}
}
}
本身安全的集合
copyonwriteArrayList list=new copyonwriteArrayList();
死锁(隐式)
当某一个同步块同时拥有“两个以上对象的锁时”,就会发生死锁问题
package XianChen;
import Nei.Ma;
public class LockTast {
public static void main(String[] args) {
Makeup m1=new Makeup("白雪公主",0);
Makeup m2=new Makeup("灰姑娘",1);
new Thread(m1).start();
new Thread(m2).start();
}
}
//镜子
class Mirror{
}
//口红
class Lipstick{
}
class Makeup extends Thread{
String name;//化妆的人
int choie;
//需要的资源只有一份,用static类来保证
static Mirror mirror=new Mirror();
static Lipstick lipstick=new Lipstick();
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Makeup(String name,int choie){
this.name=name;
this.choie=choie;
}
public void makeup() throws InterruptedException {
if(choie==0){//同时拥有两个锁会导致程序停止运行
synchronized(mirror){
System.out.println(this.name+"拿了镜子");//镜子锁
}
Thread.sleep(2000);//延时一秒后拿下一个东西
synchronized(lipstick){
System.out.println(this.name+"拿了口红");//口红锁
}
}//同时拥有两个锁会导致程序停止运行
else {
synchronized(lipstick){
System.out.println(this.name+"拿了口红");
}
Thread.sleep(1000);//延时一秒后拿下一个东西
synchronized(mirror){
System.out.println(this.name+"拿了镜子");
}
}
}
}
Lock(显示)
-
Lock接口是控制多个线程对共享资源进行访问的工具
-
ReentrantLock类实现了Lock
package XianChen;
import java.util.concurrent.locks.ReentrantLock;
public class LockTast1 {
public static void main(String[] args) {
Locktast2 locktast=new Locktast2();
new Thread(locktast).start();
new Thread(locktast).start();
new Thread(locktast).start();
}
}
class Locktast2 implements Runnable{
int ticket=10;
ReentrantLock lock=new ReentrantLock();//设置锁
@Override
public void run() {
try {
lock.lock();//开锁
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ticket > 0) {
System.out.println(ticket--);
} else {
break;
}
}
}finally {
lock.unlock();//关锁
}
}
}
生产者消费者问题
管程法
public class PcTast {
public static void main(String[] args) {
Factor factor=new Factor();
Protect protect=new Protect(factor);
Consumer consumer=new Consumer(factor);
protect.start();
consumer.start();
}
}
//生产者
class Protect extends Thread{
Factor container;
Protect( Factor container){
this.container=container;
}
@Override
public void run() {
for (int i = 1; i < 100; i++) {
System.out.println("生产了"+i+"只");
container.push(new duck(i));//将i的值赋值个id
}
}
}
//消费者
class Consumer extends Thread{
Factor container;
Consumer( Factor container){
this.container=container;
}
@Override
public void run() {
for (int i = 1; i < 100; i++) {
System.out.println("消费了"+container.pop().id+"只");
}
}
}
//产品
class duck{
int id;//编号
public duck(int id){
this.id=id;
}
}
class Factor{
//容器计数器
int count=0;
//容器大小
duck[] ducks=new duck[10];
//生产
public synchronized void push(duck id){
//容器满了
if(count==ducks.length){
//等待消费者消费,生产者等待,
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
//生产商品
ducks[count]=id;//将i从1-10分别赋值给数组0-10
count++;
//生产完毕,通知消费者
this.notifyAll();
}
}
//消费
public synchronized duck pop(){
//
if(count==0){
//等待生产者生产,消费者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//消费者消费
count--;
duck id=ducks[count];//dunk为编号id
//消费玩了,通知生产者
this.notifyAll();
return id;
}
}


