线程5大状态 :
线程常用方法 :
setPriority(int newPriority) 修改线程的优先级
static void sleep(long millis) 让当前线程休眠多少毫秒
void join() 等待该线程终止
static void yield() 当前线程暂停,其他线程执行
void interrupt() 中断线程,别用这个方式
boolean isAlive() 测试线程是否处于活动状态
为了防止线程发生异常或者数据混乱,提出以下几个建议 * 1 建议线程正常停止 * 2 可以设置一个标志位,就是循环多少次停止 * 3 不要使用stop或者destroy等过时的方法
线程休眠 :
public class TestThread implements Runnable {
@Override
public void run(){
try {
Thread.sleep(100); //线程休眠100毫秒
System.out.printf(Thread.currentThread().getName()); //打印调用者
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
TestThread t1 = new TestThread();
new Thread(t1,"张三").start(); //调用线程
new Thread(t1,"李四").start(); //调用线程
new Thread(t1,"王五").start(); //调用线程
}
}
线程礼让 :礼让其他线程先执行
public class TestThread implements Runnable {
@Override
public void run(){
try {
System.out.printf("我执行的是:"+Thread.currentThread().getName());
Thread.yield(); //线程礼让,让其他线程先执行
System.out.printf("礼让后的是:"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
TestThread t1 = new TestThread();
new Thread(t1,"张三").start();
new Thread(t1,"李四").start();
new Thread(t1,"王五").start();
}
}
线程强制执行、插队 :其他线程等待,直到插队线程跑完了其他线程才能继续执行。
public class TestThread implements Runnable {
@Override
public void run(){
try {
for (int i = 0; i < 10; i++) {
System.out.printf("我执行的是:"+Thread.currentThread().getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
TestThread t1 = new TestThread();
Thread thread = new Thread(t1);
thread.start();
for (int i = 0; i < 200; i++) {
if(i == 100){
thread.join(); //插队
}
System.out.printf("admin\n");
}
}
}
观察线程状态 :
public class TestThread implements Runnable {
@Override
public void run(){
try {
System.out.printf("线程执行中\n");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
TestThread t1 = new TestThread(); //创建线程
Thread thread = new Thread(t1);
thread.start(); //执行线程
Thread.State state = thread.getState();
System.out.printf(state+""); //打印线程状态
while (state != Thread.State.TERMINATED){//关闭线程、终止线程
state = thread.getState();
System.out.printf(state + "");
}
thread.start(); //再次调用线程时会抛出异常,因为上面已经关闭了
}
}
线程优先级 :
public class TestThread implements Runnable {
@Override
public void run(){
try {
System.out.printf(Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
TestThread t1 = new TestThread();
Thread thread = new Thread(t1,"t1");
thread.start();
Thread thread2 = new Thread(t1,"t2");
thread2.setPriority(1); //优先级1
thread2.start();
Thread thread3 = new Thread(t1,"t3");
thread3.setPriority(5); //优先级5
thread3.start();
Thread thread4 = new Thread(t1,"t4");
thread4.setPriority(10); //优先级10
thread4.start();
}
}
守护线程 :
用户线程 :用户线程是程序正常线程,他执行完了就自动停止了,可以人为的干预他执行。
守护线程 :就好比我们的java垃圾回收机制,他守护我们的程序执行。(操作日志、内存监控等等)。
线程不安全 :
//这是一个不安全的线程,模拟3个人同时强10张票的场景
public class TestThread implements Runnable {
int number = 10;
boolean flag = true;
@Override
public void run(){
try {
Thread.sleep(100);
while (flag){
System.out.printf(Thread.currentThread().getName()+"买到了第"+number+"张票\n");
number--;
flag = number > 0 ? flag : !flag; //如果票不足了就不让他们买了
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
TestThread t1 = new TestThread();
Thread thread = new Thread(t1,"t1");
thread.start();
Thread thread2 = new Thread(t1,"t2");
thread2.setPriority(1);
thread2.start();
Thread thread3 = new Thread(t1,"t3");
thread3.setPriority(5);
thread3.start();
Thread thread4 = new Thread(t1,"t4");
thread4.setPriority(10);
thread4.start();
}
}
每个线程在自己的工作内存交互,内存控制不当会导致数据不一致
t4买到了第10张票
t1买到了第10张票
t1买到了第8张票
t1买到了第7张票
t1买到了第6张票
t1买到了第5张票
t1买到了第4张票
t1买到了第3张票
t1买到了第2张票
t1买到了第1张票
t3买到了第10张票
t4买到了第9张票
t3买到了第-1张票 多个线程同时执行出现不安全的情况
t3买到了第-3张票 多个线程同时执行出现不安全的情况
提示 : new ArrayList<>() 线程是不安全的,为什么呢?因为如果多个线程去同时操作他的话他的数据会不一致,丢失或缺少。类似下面这段代码。
用下面的synchronized可以保证list安全 :
synchronized同步方法,保证线程安全 :
public class TestThread implements Runnable {
int number = 10;
boolean flag = true;
@Override
public void run(){
try {
buyATicket();
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void buyATicket(){//synchronized 同步方法,可以保证我们的线程安全,就是每个人都得排队
while (flag){
System.out.printf(Thread.currentThread().getName()+"买到了第"+number+"张票\n");
number--;
flag = number > 0 ? flag : !flag; //如果票不足了就不让他们买了
}
}
public static void main(String[] args) throws InterruptedException {
TestThread t1 = new TestThread();
Thread thread = new Thread(t1,"t1");
thread.start();
Thread thread2 = new Thread(t1,"t2");
thread2.setPriority(1);
thread2.start();
Thread thread3 = new Thread(t1,"t3");
thread3.setPriority(5);
thread3.start();
Thread thread4 = new Thread(t1,"t4");
thread4.setPriority(10);
thread4.start();
}
}
输出结果正常 :
t4买到了第10张票
t4买到了第9张票
t4买到了第8张票
t4买到了第7张票
t4买到了第6张票
t4买到了第5张票
t4买到了第4张票
t4买到了第3张票
t4买到了第2张票
t4买到了第1张票
进程已结束,退出代码为 0
synchronized 同步块 :锁的对象就是需要变化的量,就是要对我们对象进行增删改查操作的。
public class TestThread implements Runnable {
boolean flag = true;
Account account = new Account();
@Override
public void run(){
try {
buyATicket();
} catch (Exception e) {
e.printStackTrace();
}
}
public void buyATicket(){
synchronized(account){ //同步块,多个线程操作这个块,我们让操作这个对象的线程排队执行
while (flag){
System.out.printf(Thread.currentThread().getName()+"买到了第"+account.number+"张票\n");
account.number--;
flag = account.number > 0 ? flag : !flag; //如果票不足了就不让他们买了
}
}
}
public static void main(String[] args) throws InterruptedException {
TestThread t1 = new TestThread();
Thread thread = new Thread(t1,"t1");
thread.start();
Thread thread2 = new Thread(t1,"t2");
thread2.setPriority(1);
thread2.start();
Thread thread3 = new Thread(t1,"t3");
thread3.setPriority(5);
thread3.start();
Thread thread4 = new Thread(t1,"t4");
thread4.setPriority(10);
thread4.start();
}
class Account{
int number = 10;
}
}
提示 : synchronized虽然可以防止我们线程发生数据混乱,保证数据的一致性,但是我们在开发过程中也需要防止死锁,避免多个方法操作并死锁同一段代码。
Lock锁 :
public class TestThread implements Runnable {
boolean flag = true;
Account account = new Account();
private final ReentrantLock locks = new ReentrantLock(); //定义锁
@Override
public void run() {
try {
//noinspection AlibabaLockShouldWithTryFinally
locks.lock(); //对方法加锁
buyATicket();
} finally {
locks.unlock(); //对方法解锁
}
}
public void buyATicket() {
while (flag) {
System.out.printf(Thread.currentThread().getName() + "买到了第" + account.number + "张票\n");
account.number--;
flag = account.number > 0 ? flag : !flag; //如果票不足了就不让他们买了
}
}
public static void main(String[] args) throws InterruptedException {
TestThread t1 = new TestThread();
Thread thread = new Thread(t1,"t1");
thread.start();
Thread thread2 = new Thread(t1,"t2");
thread2.setPriority(1);
thread2.start();
Thread thread3 = new Thread(t1,"t3");
thread3.setPriority(5);
thread3.start();
Thread thread4 = new Thread(t1,"t4");
thread4.setPriority(10);
thread4.start();
}
class Account{
int number = 10;
}
}
线程池 :
public class TestThread implements Runnable {
String name;
public TestThread(String names){
this.name=names;
}
@Override
public void run() {
System.out.printf(name+"\n");
}
public static void main(String[] args) throws InterruptedException {
//创建一个线程池,线程数2个
ExecutorService service;
service = Executors.newFixedThreadPool(2);
//放入4个数据到线程池里面并传入名字
service.execute(new TestThread("11"));
service.execute(new TestThread("22"));
service.execute(new TestThread("33"));
service.execute(new TestThread("44"));
//关闭连接
service.shutdown();
}
}
输出
11
33
44
22
进程已结束,退出代码为 0