多线程笔记
创建线程
1 Thread
//继承Thread类,重写run()方法,!!!!使用start开启线程
//线程调用后不会马上启用,由CPU决定
public class Myrun extends Thread()
{
public void run()
{
System.out.println("111");
}
}
public static void main (String[] args)
{
Myrun my = new Myrun();
my.start();//启用线程
//my.run();是调用方法,不是启用的线程,不会有多个线程同时执行
}
2 runnable
//实现Runnable接口,重写run()方法,
public class Myrun implements Runnable()
{
public void run()
{
System.out.println("111");
}
}
public static void main (String[] args)
{
Myrun my = new Myrun();
Thread thread = new thread(my);
thread.start();
}
多个线程操作同一个对象(并发)
public class Trainticket implements Runnable {
private int ticketnums = 10;
public void run() {
while (ticketnums > 0) {
System.out.println(Thread.currentThread().getName() + "--> get " + ticketnums);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
ticketnums--;
}
}
public static void main(String[] args) {
Trainticket ticket = new Trainticket();
new Thread(ticket, "1").start();//1是线程的名字
new Thread(ticket, "2").start();
}
}
- 但是多个线程操作同一个对象可能导致数据紊乱,例如“1” “2”拿到相同序号的票,线程不安全。
Lamda 表达式
-
函数式接口:任何接口,如果只包含一种抽象方法,那么它就是一个函数式接口。而对于函数式接口,可以通通过lambda表达式来创建该接口。
public class Ilike { Like like = (/*如果有参数就填写参数*/)->{System.out.println("1111");}; //like = 参数->{System.out.println("1111");}; //like = 参数->System.out.println("1111");多行代码不可简化掉{},且多个参数时()不可省略 } like.lambda; interface Like { void lambda(); }
多线程的操作
停止
- 推荐线程自己停下,使用标志位flag,当flag为flase时停止
public class Myrun extends Thread()
{
private Boolean flag = true;
public void run()
{
int i;
while(flag){
System.out.println("myrun"+i);
}
}
public void stop()
{
this.flag = false;
}
}
public static void main (String[] args)
{
Myrun my = new Myrun();
Thread(my).start();
int i;
for(i=0;i<1000;i++)
{
if(i == 900)
{
my.stop;
System.out.println("stop");
}
System.out.println(i);
}
}
休眠
- 休眠的单位是毫秒
- 每个对象都有一个锁,sleep不会释放锁
礼让
-
礼让线程,让当前正在执行的线程暂停,但不阻塞。
-
让cpu重新调度,但是礼让不一定成功
-
将线程从运行状态转为就绪状态
class myrun implements Runnable { public void run() { System.out.println(/*Threadname+*/"start"); Thread.yield(); System.out.println(/*Threadname+*/"end"); } }
Join
- Join合并线程,待此线程执行完成之后,再执行其他线程,其他线程阻塞(插队执行
thread.join
public class Join implements Runnable{
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println("VIP:"+i);
}
}
public static void main(String[] args) throws InterruptedException {
Join j = new Join();
Thread thread = new Thread(j);
thread.start();
for (int i = 0; i < 1000; i++) {
if(i == 500)
thread.join();
System.out.println("main:"+i);
}
}
}
查看状态
-
thread.state
public class State{ public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(()->{ for (int i = 0; i < 10; i++) { try { Thread.sleep(100);//因为有休眠所以存在WAITING } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } }); Thread.State state = thread.getState(); System.out.println(state);// NEW thread.start(); state=thread.getState(); System.out.println(state);//Run while (state!=Thread.State.TERMINATED) { Thread.sleep(100); state = thread.getState(); System.out.println(state); } } }
-
线程的状态
- NEW: 尚未启动的状态
- RUNNABLE 执行的线程
- BLOCKED 被阻塞等待监视器锁定
- WAITING 等待另外一个线程执行特定动作
- TIMED_WAITING 等待另外一个线程执行动作达到指定等待时间
- TERMINATED 已经退出的线程
优先级
-
线程的优先级用1-10表示,数字大的优先级高
-
可以通过
getPriority()
获得优先级,setPriority(int a)
改变优先级//测试优先级 public class Priority { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()+"---->"+Thread.currentThread().getPriority()); Mypriority my = new Mypriority(); Thread t = new Thread(my,"0"); Thread t1 = new Thread(my,"1"); Thread t2 = new Thread(my,"2"); Thread t3 = new Thread(my,"3"); Thread t4 = new Thread(my,"4"); t1.setPriority(1); t2.setPriority(5); t3.setPriority(7); t4.setPriority(Thread.MAX_PRIORITY); t.start(); t1.start(); t2.start(); t3.start(); t4.start(); } } class Mypriority implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName()+"---->"+Thread.currentThread().getPriority()); } }
PS:跑出来可能和预想的不太一样
并发
- 同一个对象被多个线程同时操作,例如抢票
- 利用锁保证线程的安全‘
- 每个对象都拥有一把锁
- sleep不会释放锁
- synchronize:锁修改的变量
- 锁块 synchronize(obj){}
- 锁类
CopyOnWriteArrayList<> 该类是线程安全的容器
死锁
- 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都在停止执行。如果某一个同步块同时拥有两个以上对象的锁,就可能发生死锁。
- 产生死锁的程序
public class DeadBlock {
public static void main(String[] args) {
Makeup m1 =new Makeup(0,"g1");
Makeup m2 = new Makeup(1,"g2");
m1.start();
m2.start();
}
}
class Lipstick
{
}
class Mirror
{
}
class Makeup extends Thread
{
//只有一份资源
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;
String name;
Makeup(int choice,String name)
{
this.choice = choice;
this.name = name;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void makeup() throws InterruptedException {
if(choice == 0)
{
synchronized (lipstick)
{
System.out.println(this.name+"获得口红");
Thread.sleep(1000);
synchronized (mirror)// 该部分
{
System.out.println(this.name+"获得镜子");
}
}
}
else
{
synchronized (mirror)
{
System.out.println(this.name+"获得镜子");
Thread.sleep(1000);
synchronized (lipstick)// 该部分
{
System.out.println(this.name+"获得口红");
}
}
}
}
}
修改后的正确运行(部分
if(choice == 0)
{
synchronized (lipstick)
{
System.out.println(this.name+"获得口红");
Thread.sleep(1000);
}//不能有两个锁,拿出释放一个锁
synchronized (mirror)
{
System.out.println(this.name+"获得镜子");
}
}
else
{
synchronized (mirror)
{
System.out.println(this.name+"获得镜子");
Thread.sleep(1000);
}
synchronized (lipstick)
{
System.out.println(this.name+"获得口红");
}
}
显式锁Lock
- 和synchronized相比,需要手动开启和关闭锁,只能锁代码块
- 性能较好一点
private final ReentrantLock lock = new ReentrantLock();
private void m()
{
try {
lock.lock();
//代码块
}
finally {
lock.unlock();
}
}