第一种方式开辟线程
package com.qianfeng.thread;
public class ThreadCreate {
public static void main(String[] args) {
// 线程实例化
// 1.继承Thread类, 做一个线程子类(自定义线程类)
MyThread myThread = new MyThread();
// 注意
// 需要调用start方法, 使线程启动
// start方法开启一个新的线程,来执行run中的逻辑
// 如果直接调用run方法,则线程mt不会进入就绪状态
myThread.start();
System.out.println("主线程中逻辑执行结束了");
}
}
/**
* 这是自定义的线程类
*/
class MyThread extends Thread{
/**
* 需要重写run方法
* 将需要并发执行的任务写到run方法中
*/
@Override
public void run() {
for (int i = 0; i < 10; i++){
System.out.println("子线程的逻辑:" + i);
}
}
}
如果是串行的,主线程一定最后打印
第二种方式
package com.qianfeng.thread;
public class ThreadCreate {
public static void main(String[] args) {
// 线程实例化
// 1.继承Thread类, 做一个线程子类(自定义线程类)
MyThread myThread = new MyThread();
// 注意
// 需要调用start方法, 使线程启动
// start方法开启一个新的线程,来执行run中的逻辑
// 如果直接调用run方法,则线程mt不会进入就绪状态
myThread.start();
// 2.通过Runnable接口
Runnable runnable = new Runnable() {
public void run() {
for (int i = 0; i < 10; i++){
System.out.println("线程2的逻辑:" + i);
}
}
};
Thread thread = new Thread(runnable);
thread.start();
System.out.println("主线程中逻辑执行结束了");
}
}
/**
* 这是自定义的线程类
*/
class MyThread extends Thread{
/**
* 需要重写run方法
* 将需要并发执行的任务写到run方法中
*/
@Override
public void run() {
for (int i = 0; i < 10; i++){
System.out.println("子线程的逻辑:" + i);
}
}
}
线程的命名
package com.qianfeng.thread;
public class ThreadMethod {
public static void main(String[] args) {
// 线程的命名
// 1.实例化一个线程对象
// Thread thread = new Thread();
// thread.setName("custom");
// 2.实例化一个线程对象的同时,通过构造方法对线程进行命名
// Thread(Runnable r, String name)
// Thread thread = new Thread(() -> {}, "custome");
// 3.使用自定义的线程类,在实例化线程对象的同时,进行名称的赋值
// 需要给线程类添加对应的构造方法
MyThread2 thread = new MyThread2("custom");
System.out.println(thread.getName());
}
}
class MyThread2 extends Thread{
public MyThread2() {
}
public MyThread2(String name){
// super(name);
this.setName(name);
}
}
线程休眠
package com.qianfeng.thread;
public class ThreadMethod {
public static void main(String[] args) {
threadSleep();
}
private static void threadSleep() {
MyThread2 myThread2 = new MyThread2();
myThread2.start();
}
}
class MyThread2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++){
System.out.println(i);
// 线程休眠
// 1.参数:毫秒为单位的时间差
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
每一秒打印一个数
线程的优先级
package com.qianfeng.thread;
public class ThreadMethod {
public static void main(String[] args) {
threadPriority();
}
private static void threadPriority() {
// 设置线程的优先级,只是修改这个线程可以去抢到cpu时间片的概率
// 并不是优先级高的线程一定能签到cpu的时间片
// 优先级的设置,是一个整数[0,10]的整数,默认为5
// Runnable runnable = new Runnable() {
// @Override
// public void run() {
// for (int i = 0; i < 100; i++){
// System.out.println(Thread.currentThread().getName() + ":" + i);
// }
// }
// }
Runnable runnable = () -> {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
};
Thread t1 = new Thread(runnable, "Thread-1");
Thread t2 = new Thread(runnable, "Thread-2");
// 设置优先级必须要放到这个线程开始执行(start)之前
t1.setPriority(10);
t2.setPriority(1);
t1.start();
t2.start();
}
}
class MyThread2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++){
System.out.println(i);
// 线程休眠
// 1.参数:毫秒为单位的时间差
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程的礼让
package com.qianfeng.thread;
public class ThreadMethod {
public static void main(String[] args) {
threadYield();
}
private static void threadPriority() {
// 设置线程的优先级,只是修改这个线程可以去抢到cpu时间片的概率
// 并不是优先级高的线程一定能签到cpu的时间片
// 优先级的设置,是一个整数[0,10]的整数,默认为5
// Runnable runnable = new Runnable() {
// @Override
// public void run() {
// for (int i = 0; i < 100; i++){
// System.out.println(Thread.currentThread().getName() + ":" + i);
// }
// }
// }
Runnable runnable = () -> {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
};
Thread t1 = new Thread(runnable, "Thread-1");
Thread t2 = new Thread(runnable, "Thread-2");
// 设置优先级必须要放到这个线程开始执行(start)之前
t1.setPriority(10);
t2.setPriority(1);
t1.start();
t2.start();
}
/**
* 线程的礼让
*/
private static void threadYield() {
// 线程礼让,指的是当前的运行状态的线程释放自己的cpu资源,由运行状态,回到就绪状态,并重新开始争抢cpu资源
Runnable r = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ";" + i);
if (i == 3) {
Thread.yield();
}
}
}
};
Thread t1 = new Thread(r,"thread-1");
Thread t2 = new Thread(r,"thread-2");
t1.start();
t2.start();
}
}
class MyThread2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 10; i++){
System.out.println(i);
// 线程休眠
// 1.参数:毫秒为单位的时间差
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
临界资源问题展示
进程资源不共享,但是线程资源共享
package com.qianfeng.sourceconflict;
public class SourceConflict {
// 演示临界资源问题
// 某个景点由4个售票员同时在售票
public static void main(String[] args) {
// 实例化4个售票员,用4个线程模拟4个售票员
Runnable r = () -> {
while (TicketCenter.restCount >0) {
System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter.restCount + "张");
}
};
// 用四个线程模拟4个售票员
Thread t1 = new Thread(r,"thread - 1");
Thread t2 = new Thread(r,"thread - 2");
Thread t3 = new Thread(r,"thread - 3");
Thread t4 = new Thread(r,"thread - 4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class TicketCenter {
// 描述剩余的票的数量
public static int restCount = 100;
}
解决临界资源问题
同步代码段
package com.qianfeng.sourceconflict;
public class SynchronizedDemo {
public static void main(String[] args) {
// 实例化4个售票员,用4个线程模拟4个售票员
Runnable r = () -> {
while (TicketCenter.restCount >0) {
// 对象锁: ""
// 类锁:
// 需要保证一点,多个线程看到的锁,需要时同一把锁!!!
synchronized (SynchronizedDemo.class){
if (TicketCenter2.restCount <= 0) {
return;
}
System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter2.restCount + "张");
}
}
};
// 用四个线程模拟4个售票员
Thread t1 = new Thread(r,"thread - 1");
Thread t2 = new Thread(r,"thread - 2");
Thread t3 = new Thread(r,"thread - 3");
Thread t4 = new Thread(r,"thread - 4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class TicketCenter2{
// 描述剩余的票的数量
public static int restCount = 100;
}
同步方法
package com.qianfeng.sourceconflict;
public class SynchronizedFunction {
public static void main(String[] args) {
// 实例化4个售票员,用4个线程模拟4个售票员
Runnable r = () -> {
while (TicketCenter.restCount >0) {
// 对象锁: ""
// 类锁:
// 需要保证一点,多个线程看到的锁,需要时同一把锁!!!
soldTicket();
}
};
// 用四个线程模拟4个售票员
Thread t1 = new Thread(r,"thread - 1");
Thread t2 = new Thread(r,"thread - 2");
Thread t3 = new Thread(r,"thread - 3");
Thread t4 = new Thread(r,"thread - 4");
t1.start();
t2.start();
t3.start();
t4.start();
}
/**
* 同步方法
* 静态方法: 同步锁就是 类锁 当前类.class
* 非静态方法: 同步锁 是 this
*/
private synchronized static void soldTicket() {
if (TicketCenter.restCount <= 0) {
return;
}
System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter.restCount + "张");
}
}
显示锁
package com.qianfeng.sourceconflict;
import java.util.concurrent.locks.ReentrantLock;
public class LockDemo {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
// 实例化4个售票员,用4个线程模拟4个售票员
Runnable r = () -> {
while (TicketCenter2.restCount > 0) {
// 对临界资源上锁
lock.lock();
if (TicketCenter2.restCount <= 0) {
return;
}
System.out.println(Thread.currentThread().getName() + "卖出一张票,剩余" + --TicketCenter2.restCount + "张");
// 对临界资源解锁
lock.unlock();
}
};
// 用四个线程模拟4个售票员
Thread t1 = new Thread(r, "thread - 1");
Thread t2 = new Thread(r, "thread - 2");
Thread t3 = new Thread(r, "thread - 3");
Thread t4 = new Thread(r, "thread - 4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
死锁
package com.qianfeng.sourceconflict;
public class DeadLock {
public static void main(String[] args) {
// 死锁: 多个线程彼此持有对方所需要的锁对象,而不释放自己的锁
Runnable runnable1 = () -> {
synchronized ("A") {
System.out.println("A线程持有了A锁,等待B锁");
synchronized ("B") {
System.out.println("A线程持有了A锁和B锁");
}
}
};
Runnable runnable2 = () -> {
synchronized ("B") {
System.out.println("B线程持有了B锁,等待A锁");
synchronized ("A"){
System.out.println("B线程持有了A锁和B锁");
}
}
};
Thread thread1 = new Thread(runnable1);
Thread thread2 = new Thread(runnable2);
thread1.start();
thread2.start();
}
}
解决死锁
package com.qianfeng.sourceconflict;
public class DemoLock {
public static void main(String[] args) {
// 死锁: 多个线程彼此持有对方所需要的锁对象,而不释放自己的锁
// wait:等待, 是Object类中的一个方法,当前的线程释放自己的标记,并且让出cpu资源,使得当前的线程进入等待队列中。
// notify: 通知, 是Object类中的一个方法, 唤醒等待队列中的一个线程,使这个线程进入锁池。
// notifyAll: 通知, 是Object类中的一个方法,唤醒等待队列中所有的线程,并使这些线程进入锁池。
Runnable runnable1 = () -> {
synchronized ("A") {
System.out.println("A线程持有了A锁,等待B锁");
try {
"A".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized ("B") {
System.out.println("A线程持有了A锁和B锁");
}
}
};
Runnable runnable2 = () -> {
synchronized ("B") {
System.out.println("B线程持有了B锁,等待A锁");
synchronized ("A"){
System.out.println("B线程持有了A锁和B锁");
"A".notifyAll();
}
}
};
Thread thread1 = new Thread(runnable1);
Thread thread2 = new Thread(runnable2);
thread1.start();
thread2.start();
}
}