根据本人多年从业以及学习经验,录制了一套最新的Java精讲视频教程,如果你现在也在学习Java,在入门学习Java的过程当中缺乏系统的学习教程,你可以加QQ群654631948领取下学习资料,面试题,开发工具等,群里有资深java老师做答疑,每天也会有基础部分及架构的直播课,也可以加我的微信renlliang2013做深入沟通,只要是真心想学习Java的人都欢迎。
java基础教程:https://ke.qq.com/course/149432?tuin=57912c43
Java分布式互联网架构/微服务/高性能/springboot/springcloud:
https://ke.qq.com/course/179440?tuin=57912c43
子类要重写run方法。
public class MyThread extends Thread {
private String name;
public MyThread(String name){
this.name = name;
}
/**
* 这就是线程执行的逻辑体
*/
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println(name+"下载了"+i+"%");
}
}
}
测试代码:
public class ThreadTest {
public static void main(String[] args) {
//创建一个线程的对象
MyThread mt = new MyThread("肖申克的救赎");
//启动一个线程
mt.start();
//创建一个线程的对象
MyThread mt1 = new MyThread("当幸福来敲门");
//启动一个线程
mt1.start();
//System.out.println("方法结束");
}
}
1.2实现Runnable接口来创建线程
示例代码
public class DownLoad implements Runnable {
private String name;
public DownLoad(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println(name+"下载了"+i+"%");
}
}
}
测试代码:
public class ThreadTest {
public static void main(String[] args) {
//创建线程对象
Thread t = new Thread(new DownLoad("肖申克的救赎"));
Thread t1 = new Thread(new DownLoad("当幸福来敲门"));
t.start();
t1.start();
}
}
2.线程的执行原理
3.线程生命周期
1.新建: 线程被new出来
2.准备就绪:线程具有执行的资格,即线程调用了start(),没有执行的权利
3.运行:具备执行的资格和具备执行的权利
4.阻塞:没有执行的资格和执行权利
5.销毁: 线程的对象变成垃圾,释放资源。
4.并发
互联网的项目中存在着大量的并发的案例,如卖火车票,电商网站。
范例:火车站有100张票,4个窗口同时买票。
分析:4个窗口是4个线程同时在运行,100票是4个线程的共享资源。
语法:
synchronized(锁对象){
//操作共享资源的代码
}
同步代码加在什么地方?
1.代码被多个线程访问
2.代码中有共享的数据
3.共享数据被多条语句操作。
public class SaleTicketThread extends Thread {
private String name;
/**
* 定义共享的数据100张票
*/
static int tickets = 100;
//创建一个锁对象,这个对象是多个线程对象共享的数据
static Object obj = new Object();
public SaleTicketThread(String name) {
this.name = name;
}
@Override
public void run() {
//卖票是持续的
while (true){
synchronized (obj){
if(tickets > 0){
System.out.println(name+"卖出座位是"+(tickets--)+"号");
}else{
break;
}
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+"卖票结束");
}
}
测试代码:
public class ThreadTest {
public static void main(String[] args) {
SaleTicketThread t1 = new SaleTicketThread("窗口1");
SaleTicketThread t2 = new SaleTicketThread("窗口2");
SaleTicketThread t3 = new SaleTicketThread("窗口3");
SaleTicketThread t4 = new SaleTicketThread("窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
第二种同步处理
public class SaleTicket implements Runnable {
/**
* 多个线程共享的100张票
*/
int tickets = 100;
//创建一个锁对象,这个对象是多个线程对象共享的数据
Object obj = new Object();
@Override
public void run() {
//卖票是持续的
while (true){
synchronized (obj){
if(tickets > 0){
System.out.println(Thread.currentThread().getName()+"卖出座
位是"+(tickets--)+"号");
}else{
break;
}
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"卖票结束");
}
}
测试代码
public class ThreadTest {
public static void main(String[] args) {
//创建一个卖票的对象
SaleTicket st = new SaleTicket();
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");
Thread t4 = new Thread(st, "窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
1.3Synchronized如果放在对象方法上
public class SaleTicket implements Runnable {
/**
* 多个线程共享的100张票
*/
int tickets = 100;
//创建一个锁对象,这个对象是多个线程对象共享的数据
Object obj = new Object();
@Override
public void run() {
//卖票是持续的
while (true){
if(saleTickets()){
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"卖票结束");
}
/*public boolean saleTickets(){
synchronized (obj){
boolean isFinish = false;
if(tickets > 0){
System.out.println(Thread.currentThread().getName()+"卖出座位是"+(tickets--)+"号");
}else{
isFinish = true;
}
return isFinish;
}
}*/
/**
*
* @return 如果一个对象方法上有synchronized的话那么锁的对象就是this
*/
public synchronized boolean saleTickets(){
//synchronized (obj){
boolean isFinish = false;
if(tickets > 0){
System.out.println(Thread.currentThread().getName()+"卖出座位是"+(tickets--)+"号");
}else{
isFinish = true;
}
return isFinish;
//}
}
}
Synchronized如果在类方法上那么锁对象就是类的类对象
public class SaleTicketThread extends Thread {
private String name;
/**
* 定义共享的数据100张票
*/
static int tickets = 100;
//创建一个锁对象,这个对象是多个线程对象共享的数据
static Object obj = new Object();
public SaleTicketThread(String name) {
super(name);
this.name = name;
}
@Override
public void run() {
//卖票是持续的
while (true){
if(saleTickets()){
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+"卖票结束");
}
public static synchronized boolean saleTickets(){
boolean isFinish = false;
if(tickets > 0){
System.out.println(Thread.currentThread().getName()+"卖出座位是"+(tickets--)+"号");
}else{
isFinish = true;
}
return isFinish;
}
}
测试代码:
public class ThreadTest {
public static void main(String[] args) {
SaleTicketThread t1 = new SaleTicketThread("窗口1");
SaleTicketThread t2 = new SaleTicketThread("窗口2");
SaleTicketThread t3 = new SaleTicketThread("窗口3");
SaleTicketThread t4 = new SaleTicketThread("窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
5.休眠
在做服务器端的程序的时候都需要给一个休眠的时间,在没有synchronized代码块里面会让出cpu的资源。
public static void main(String[] args) {
while(true){
System.out.println(new Date());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
休眠在同步代码块内不会让出cpu
synchronized (ojb){
try {
//我们休眠如果在synchronized内部就不会让出cpu的资源
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
6.线程间的通信
生产者生成水果,如果水果没有被买走那么就不生产处于等待状态,如果水果被消费者买走这时候消费者会通知生产者告诉他我们已经把水果买走了请生产,消费者同理,如果水果已经生产出来那么就买走,买走之后再通知生产者水果已经没了请生产。
注意:
1.线程间的通信共享数据一定要有同步代码块synchronized
2.一定要有wait和notify,而且二者一定是成对出现。
3.生产者和消费者的线程实现一定是在while(true)里面
第一种实现方式:
public class Basket {
private boolean isEmpty;
public boolean isEmpty() {
return isEmpty;
}
public void setEmpty(boolean empty) {
isEmpty = empty;
}
}
生产者:
public class Producer extends Thread {
private Basket basket;
public Producer(Basket basket){
super();
this.basket = basket;
}
@Override
public void run() {
while(true){
//定义一个同步代码块
synchronized (basket){
try {
if(!basket.isEmpty()){
//线程等待的状态
basket.wait();
}
System.out.println("生成水果");
basket.setEmpty(false);
//通知在这个共享对象上等待的线程
basket.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
消费者:
package cn.tx.demo8;
public class Consumer extends Thread{
private Basket basket;
public Consumer(Basket basket){
super();
this.basket = basket;
}
@Override
public void run() {
while(true){
//定义一个同步代码块
synchronized (basket){
try {
if(basket.isEmpty()){
//线程等待的状态
basket.wait();
}
System.out.println("消费水果");
basket.setEmpty(true);
//通知在这个共享对象上等待的线程
basket.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
线程的第二种实现方式实现runnable
public class Basket {
private boolean isEmpty;
public boolean isEmpty() {
return isEmpty;
}
public void setEmpty(boolean empty) {
isEmpty = empty;
}
}
生产者
package cn.tx.demo9;
public class Producer implements Runnable {
private Basket basket;
public Producer(Basket basket){
super();
this.basket = basket;
}
@Override
public void run() {
while(true){
//定义一个同步代码块
synchronized (basket){
try {
if(!basket.isEmpty()){
//线程等待的状态
basket.wait();
}
System.out.println("生成水果");
basket.setEmpty(false);
//通知在这个共享对象上等待的线程
basket.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
消费者
package cn.tx.demo9;
public class Consumer implements Runnable{
private Basket basket;
public Consumer(Basket basket){
super();
this.basket = basket;
}
@Override
public void run() {
while(true){
//定义一个同步代码块
synchronized (basket){
try {
if(basket.isEmpty()){
//线程等待的状态
basket.wait();
}
System.out.println("消费水果");
basket.setEmpty(true);
//通知在这个共享对象上等待的线程
basket.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
测试:
public class Test {
public static void main(String[] args) {
Basket basket = new Basket();
Producer producer = new Producer(basket);
Consumer consumer = new Consumer(basket);
Thread t = new Thread(producer);
Thread t1 = new Thread(consumer);
t.start();
t1.start();
}
}
7.线程的优先级
我们可以通过public final void setPriority(int newPriority)
来设置线程的优先级,但是优先级并不是绝对的,只是先对来说比其他的线程得到CPU的资源机会多一些。
public class ThreadTest {
public static void main(String[] args) {
//创建一个线程的对象
MyThread mt = new MyThread("肖申克的救赎");
//创建一个线程的对象
MyThread mt1 = new MyThread("当幸福来敲门");
mt.setPriority(Thread.MAX_PRIORITY);
//启动一个线程
mt.start();
//启动一个线程
mt1.start();
//System.out.println("方法结束");
}
}
8.加入线程
join线程会抢先拿到CPU来执行线程,然后其他的线程再来执行
加入线程必须要在先执行的线程的start下面来执行
public class ThreadTest {
public static void main(String[] args) {
//创建一个线程的对象
MyThread mt = new MyThread("肖申克的救赎");
//创建一个线程的对象
MyThread mt1 = new MyThread("当幸福来敲门");
MyThread mt2 = new MyThread("魔戒1");
mt.start();
try {
//加入线程必须要在先执行的线程的start下面来执行
mt.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
mt1.start();
mt2.start();
}
}
9.让出线程
当前的线程从运行阶段回到就绪阶段,目的是把CPU的资源让给其他的线程。
public class MyThread extends Thread {
private String name;
public MyThread(String name){
this.name = name;
}
/**
* 这就是线程执行的逻辑体
*/
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println(name+"下载了"+i+"%");
//让出线程
Thread.yield();
}
}
}
10.守护线程
守护线程会随着主线程的结束而结束。
public class ThreadTest {
public static void main(String[] args) {
//创建一个线程的对象
MyThread mt = new MyThread("肖申克的救赎");
//设置守护线程
mt.setDaemon(true);
mt.start();
System.out.println("主线程结束");
}
}
11.死锁
在做线程开发的时候要避免出现死锁。
死锁程序
public class DeadLockThread extends Thread {
int flag;
@Override
public void run() {
if(flag == 1){
synchronized (Lock.lock1){
System.out.println("进入锁1");
synchronized (Lock.lock2){
System.out.println("进入锁1中的锁2");
}
}
}else{
synchronized (Lock.lock2){
System.out.println("进入锁2");
synchronized (Lock.lock1){
System.out.println("进入锁2中的锁1");
}
}
}
}
}
测试:
public class DeadLockTest {
public static void main(String[] args) {
DeadLockThread dt = new DeadLockThread();
dt.flag = 1;
DeadLockThread dt1 = new DeadLockThread();
dt.start();
dt1.start();
}
}