41.线程
2021-05-05 07:29
标签:over dex contex target number 导致 没有 顺序 之间 例如记事本:我们在打开记事本的时候打开页面设置: 上面这种情况说明记事本整个执行流程只有一条执行路径,是单线程程序 再例如QQ: 上面QQ的聊天界面和好友搜索界面有各自的执行路径,说明QQ是多线程程序 结果:Thread-n.... 帯参构造方法设置线程名称: 1.线程类要添加帯参构造方法,默认调用父类帯参构造方法 每个线程执行一下之后都会"等待"一秒钟,所以大家执行的很均匀 卖票结果: 41.线程 标签:over dex contex target number 导致 没有 顺序 之间 原文地址:https://www.cnblogs.com/luzhanshi/p/13193279.html1.进程
2.线程
3.多线程实现方式
方式1:
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i){
System.out.println(i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
// thread1.run();//并没有启动线程,和普通方法调用一样
// thread2.run();
// void start?() 导致此线程开始执行; Java虚拟机调用此线程的run方法。
thread1.start();
thread2.start();
}
}
方式2:
//定义一个类实现Runnable接口
public class MyRunable implements Runnable{
// 重写run方法
@Override
public void run() {
for(int i=0;i){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public static void main(String[] args) {
// 创建MyRunable对象
MyRunable myRunable = new MyRunable();
// 创建Thread对象并将myRunable对象作为Thread构造方法参数传递
Thread thread1 = new Thread(myRunable, "火车票");
Thread thread2 = new Thread(myRunable, "飞机票");
thread1.start();
thread2.start();
}
4.设置和获取线程名称
获取默认线程名称
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i){
System.out.println(getName()+":"+i);
}
}
/**
* public class Thread implements Runnable {
*private volatile String name;
*public Thread() {
* init(null, null, "Thread-" + nextThreadNum(), 0);
* }
*private void init(ThreadGroup g, Runnable target, String name,long stackSize) {
* init(g, target, name, stackSize, null, true);
* }
*private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
* this.name = name;
* }
* private static int threadInitNumber;0,1,2...
*private static synchronized int nextThreadNum() {
* return threadInitNumber++;//先return后++,所以依次返回0,1,2...
* }
*
* public final String getName() {
* return name;
* }
* }
*/
}
设置线程名称
thread1.setName("高铁");
thread2.setName("飞机");
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i){
System.out.println(getName()+":"+i);
}
}
public MyThread() {
}
public MyThread(String name) {
super(name);
}
}
MyThread myThread = new MyThread("线程1");
获取当前类线程名称
//static Thread currentThread?() 返回对当前正在执行的线程对象的引用。
System.out.println(Thread.currentThread().getName());
5.线程调度(线程优先级)
// IllegalArgumentException - 如果优先级不在 MIN_PRIORITY到 MAX_PRIORITY范围内。
// thread1.setPriority(10000);//IllegalArgumentException:抛出表示一种方法已经通过了非法或不正确的参数。
// 从下面我们可以得知线程优先级的设置范围在1~10之间,并且默认值是5
System.out.println(Thread.MAX_PRIORITY);//10
System.out.println(Thread.MIN_PRIORITY);//1
System.out.println(Thread.NORM_PRIORITY);//5
// 设置优先级
thread1.setPriority(1);
thread2.setPriority(5);
thread3.setPriority(10);
thread1.start();
thread2.start();
thread3.start();
6.线程控制
sleep
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i){
System.out.println(getName()+":"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.setName("飞机");
t2.setName("火车");
t3.setName("汽车");
t1.start();
t2.start();
t3.start();
}
join
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i){
System.out.println(getName()+":"+i);
}
}
}
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.setName("皇上");
t2.setName("三皇子");
t3.setName("六皇子");
//皇上死了之后三皇子和六皇子才 开始争夺"皇位(CPU)"
t1.start();
t1.join();
t2.start();
t3.start();
}
SetDaemon()
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i){
System.out.println(getName()+":"+i);
}
}
}
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.setName("悟空");
t2.setName("八戒");
t3.setName("老沙");
// 悟空,八戒,沙僧,都是守护师傅的,那么如果师傅"死掉了(线程结束)",他们三个也没有存在的必要了,也应该停止
// 这里我们将上面三个线程设置为守护线程,当运行的线程都是守护线程时.java虚拟机将退出:
t1.setDaemon(true);
t2.setDaemon(true);
t3.setDaemon(true);
t1.start();
t2.start();
t3.start();
Thread.currentThread().setName("师傅");
for (int i=0;i){
System.out.println( Thread.currentThread().getName()+":"+i);
Thread.currentThread().sleep(1);
}
}
7.线程声明周期
8.线程同步
卖票案例
//定义一个类实现Runnable接口并重写run方法
public class SellTicket implements Runnable {
// 定一个票数变量
private int tickets = 100;
@Override
public void run() {
// 相同的票卖出了多次???卖负数票???
while (true) {//定义死循环,一直卖票
// 判断票数是否为0
// 假设thread1抢到了CPU执行权
if (tickets > 0) {
try {//通过sleep模拟卖出每张票所需要的时间
Thread.sleep(100);
// thread1休息100毫秒
// 此时thread2抢到了CPU执行权,thread2开始执行,执行到这里thread2也休息100毫秒
// 此时thread3抢到了CPU执行权,thread3开始执行,执行到这里thread3也休息100毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// 假设线程按照顺序醒过来
// thread1抢到了CPU执行权,在控制台输出:窗口1正在出售第100张票
System.out.println(Thread.currentThread().getName() + ":正在卖第" + tickets + "张票");
// thread2抢到了CPU执行权,在控制台输出:窗口2正在出售第100张票
// thread3抢到了CPU执行权,在控制台输出:窗口3正在出售第100张票
tickets--;
// 如果三个线程还是按照上面的顺序来,这次就执行了3次"--"的操作,tickets变成了97,,,最终同理就出现了卖"负数票"
}
}
}
// 创建卖票窗口对象
SellTicket sellTicket = new SellTicket();
// 创建三个线程对应三个卖票窗口
Thread thread1 = new Thread(sellTicket, "窗口1");
Thread thread2 = new Thread(sellTicket, "窗口2");
Thread thread3 = new Thread(sellTicket, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
卖票案例问题解决
同步代码块:
public class SellTicket implements Runnable {
private int tickets = 100;
private Object o=new Object();//这里定义一个任意Object对象,保证是同一把锁
@Override
public void run() {
while (true) {
// thread1抢到了CPU执行权
synchronized (o){
if (tickets > 0) {
try {
// thread1进来之后就会把代码锁起来
Thread.sleep(100);
// thread1休息100毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
// thread1抢到了CPU执行权,在控制台输出:窗口1正在出售第100张票
System.out.println(Thread.currentThread().getName() + ":正在卖第" + tickets + "张票");
tickets--;
}
// thread1出来之后解锁上面代码
}
}
}
}
同步方法:
public class SellTicket implements Runnable {
private static int tickets = 100;
private Object o=new Object();
private int X=0;
@Override
public void run() {
while (true) {
if(X%2==0){
// synchronized (o){
// synchronized (this){
synchronized (SellTicket.class){
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":正在卖第" + tickets + "张票");
tickets--;
}
}
}else{
sellTicket();
}
X++;
}
}
// private synchronized void sellTicket() {
// if (tickets > 0) {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + ":正在卖第" + tickets + "张票");
// tickets--;
// }
// }
private static synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":正在卖第" + tickets + "张票");
tickets--;
}
}
}
9.线程安全的类
StringBuffer stringBuffer = new StringBuffer();//线程安全,多线程情况下使用
StringBuilder stringBuilder = new StringBuilder();//线程不安全,非多线程情况使用
Vector
10.Lock
public class LockTest implements Runnable {
private int tickets = 100;
private Lock lock=new ReentrantLock();
@Override
public void run() {
while (true) {
try {
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":正在卖第" + tickets + "张票");
tickets--;
}
} catch (Exception e) {
e.printStackTrace();
} finally { //无论什么情况下都要释放锁
lock.unlock();
}
}
}
}
上一篇:JAVA学习之-I/O流
下一篇:c++怎么现在不坑