线程与进程
2390. 从字符串中移除星号
给你一个包含若干星号
*
的字符串s
。在一步操作中,你可以:
- 选中
s
中的一个星号。- 移除星号 左侧 最近的那个 非星号 字符,并移除该星号自身。
返回移除 所有 星号之后的字符串**。**
注意:
- 生成的输入保证总是可以执行题面中描述的操作。
- 可以证明结果字符串是唯一的。
示例 1:
输入:s = "leet**cod*e" 输出:"lecoe" 解释:从左到右执行移除操作: - 距离第 1 个星号最近的字符是 "leet**cod*e" 中的 't' ,s 变为 "lee*cod*e" 。 - 距离第 2 个星号最近的字符是 "lee*cod*e" 中的 'e' ,s 变为 "lecod*e" 。 - 距离第 3 个星号最近的字符是 "lecod*e" 中的 'd' ,s 变为 "lecoe" 。 不存在其他星号,返回 "lecoe" 。
StringBuilder内置加,删。
- 复习
- 方案一:先放进去在扫描
- 方案二:一个个放,遇到*删除and弹出栈顶。
- 方案三:放到Stringbuilder
引入
- cpu主要用于寻址。
- 摩尔定律
是由英特尔(Intel)创始人之一戈登·摩尔(Gordon Moore)提出来的。其内容为:当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍。换言之,每一美元所能买到的电脑性能,将每隔18-24个月翻一倍以上。这一定律揭示了信息技术进步的速度。 尽管这种趋势已经持续了超过半个世纪,摩尔定律仍应该被认为是观测或推测,而不是一个物理或自然法。预计定律将持续到至少2015年或2020年。然而,2010年国际半导体技术发展路线图的更新增长已经放缓在2013年年底,之后的时间里晶体管数量密度预计只会每三年翻一番。
进程是任务,线程是分配任务。
进程
并发与并行:
多线程的缺点:管理不便。
new,start(创建,就绪),运行,堵塞,自然死亡。
package com.ffyc.thread;
/**
* 写10个1~10
* 分任务!
* @param args
*/
public class ThreadDemo02 extends Thread{
public static void main(String[] args) {
Thread t1 = new ThreadDemo02();
Thread t2 = new ThreadDemo02();
t2.start();//ready
t1.start();//就绪,CPU有时间片才会运行,也不是一定运行。
}
@Override
public void run() {
for (int i = 1; i <=10 ; i++) {
System.out.print(i+"\t");
}
System.out.println();
}
}
线程生命周期
*核心
package com.ffyc.thread;
/**
* Runnable接口实现(可以继承)
* why:java单继承、多实现
*/
public class ThreadDemo03 implements Runnable{
private String name;
public ThreadDemo03(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(this.name+"-->"+i);
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new ThreadDemo03("A"));
Thread t2 = new Thread(new ThreadDemo03("B"));
t2.start();
t1.start();
}
}
Runnable
-
对比函数式接口 VS 匿名内部类(接口在内部实现)
-
点灰色–>lambda表示式
-
lambda表示式
-
List排顺序Camparator o1 - o2;逆序 o2- o1。
-
二维数组排序
package com.ffyc.thread;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class SortDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();//动态数组
list.add(1);
list.add(3);
list.add(2);
System.out.println(list);//无序:1 3 2
//自己写排序【empty】
// OR jdk排
list.sort(new A());//写一个A排序
System.out.println("Sort:"+list);
list.sort(new Comparator<Integer>() {//lambda
@Override
public int compare(Integer f, Integer l) {
return f-l;
}
});
System.out.println("first-last:"+list);
}
}
package com.ffyc.thread;
public class ThreadDemo05 {
public static void main(String[] args) {
/**
* Runnable匿名内部类
*/
Thread t1 = new Thread(new Thread(() -> {
for (int i=1;i<10;i++){
System.out.println("A->"+i);
}
}));
Thread t2 = new Thread(new Thread(() -> {
for (int i=1;i<20;i++){
System.out.println("B->"+i);
}
}));
t1.start();
t2.start();
}
}
block():阻塞
三种解决方法:
- sleep()–>唤醒前要就绪
- yield
- join
- wait——高级别–》对all对象
可怕
List扩容时可能加入新的元素,不安全。
守护线程和用户线程
守护最后一个用户线程结束才结束。
守护线程–> .setDaemon(true)
package com.ffyc.thread;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 守护线程
*/
public class ProtectThread {
public static void main(String[] args) {
Thread t1 = new Thread(()->{
while (true){
try {
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss");
System.out.println(sdf.format(d));
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
Thread t2 = new Thread(()->{
for (int i = 0; i < 100; i++) {
try {
System.out.println("我是00"+i);
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t1.setDaemon(true);
t1.start();
t2.start();
}
}
用户线程
复习:
- 线程
- 集合
- 面向对象
线程安全
回顾生命周期
三大特性
- 原子性(理论上)——线程任务不可再分。
- 可见性——线程之间的操作互相不可见。
- 有序性——程序运行顺序不能改变。
特性一:原子性 代码举例
int i = 1;
i++;
原子类–多线程时±/*安全。
AtomicXXX
package com.ffyc.Thread; import java.util.concurrent.atomic.AtomicInteger; /** * 特性一:原子性 * i++/++i ===> 不安全---why:两步完成。 */ public class ThreadDemo01 { //static int x = 1; static AtomicInteger a = new AtomicInteger(1); public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(a.addAndGet(1)); try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { try { for (int i = 0; i < 100; i++) { System.out.println(a.addAndGet(1)); Thread.sleep(100); } } catch (InterruptedException e) { throw new RuntimeException(e); } } }); // 启动线程 t1.start(); t2.start(); } }
特性二:互盲
但不能保证有序。
Eg:
升级
package com.ffyc.thread;
public class ThreadDemo02 {
static volatile boolean flag = false;
public static void main(String[] args) {
//线程A如果,flag为true,就运行打印语句 A: true
Thread t1 = new Thread(() -> {
while (true) {
if (flag) {
System.out.println("A:" + flag);
}
}
});
//100ms之后将flag变为true
Thread t2 = new Thread(() -> {
try {
Thread.sleep(100);
flag = true;
System.out.println("B:" + flag);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
t1.start();
t2.start();
}
}
特性三:不能改变固有顺序
“重点”解决线程安全方案——*锁🔒
原理
- 每一个对象只有一把锁,
- 每个线程抢锁,先拿到的线程就是锁的持有者。
- 持有锁的线程访问有synchronized标记的方法/代码块
- 离开synchronized,线程releas(释放)锁🔒
现实场景:买票程序
ticket
package com.ffyc.ticket;
public class Ticket {
private Integer num;
private String name;
public Ticket(Integer num) {
this.num = num;
}
public Ticket(Integer num, String name) {
this.num = num;
this.name = name;
}
/**
* 取出剩余票数
* @return
*/
public Integer getNum() {
return num;
}
/**
* 卖票
* @param name
* //sy 同步 解决
*/
public synchronized void sold(String name){
System.out.println("站点"+name+"购买成功,余票"+ (--num)+"票");//why前减
}
}
tivketThread
package com.ffyc.ticket;
public class TicketsThread extends Thread{
private final String name;
private final Ticket ticket;
public TicketsThread(Ticket ticket,String name){
this.ticket=ticket;
this.name = name;
}
@Override
public void run(){
// synchronized (ticket.getNum()){//解决-1,-2票的打印问题,但是全是A买的。
while (ticket.getNum()>2){//笨办法解决
try {
sleep(100);
ticket.sold(name);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
//}
}
TicketTest
package com.ffyc.ticket;
public class TestTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket(100);
Thread a = new TicketsThread(ticket, "A");
Thread b= new TicketsThread(ticket,"B");
Thread c = new TicketsThread(ticket,"C");
a.start();
c.start();
b.start();
}
}
Ways:
- 方法体
- 方法里**{代码块},注意不能有基本数据类型,要用包装类型。**
改造Atomic
sy联系:StringBuffer,Vector。
Asy异步 ——》 前端里用
持有锁
死锁
sy(A){
sy(B){ }
}
Resource
package com.ffyc.lock;
public class Resource {
private String name;
public Resource(String name) {
this.name= name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Resource{" +
"name='" + name + '\'' +
'}';
}
}
DeadLockThread
package com.ffyc.lock;
public class DeadLockThread extends Thread{
private Resource x;
private Resource y;
public DeadLockThread(Resource x, Resource y) {
this.x = x;
this.y = y;
}
@Override
public void run() {
synchronized (x){
System.out.println(x.getName()+"锁定"+x.getName()+"成功...");
try {
sleep(200);
System.out.println(x.getName()+"准备--->锁定"+y.getName()+">>>>");
synchronized (y){
System.out.println(x.getName()+"锁定"+y.getName()+"成功...");
}
System.out.println("释放"+y.getName()+"成功...");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("释放"+x.getName()+"成功...");
}
}
Main
package com.ffyc.lock;
public class Main {
public static void main(String[] args) {
Resource lwh = new Resource("李文豪");
Resource wzy = new Resource("隗子垚");
Resource fzy = new Resource("冯正阳");
Thread a = new DeadLockThread(lwh, fzy);
Thread b = new DeadLockThread(fzy, wzy);
Thread c = new DeadLockThread(wzy, lwh);
a.start();
b.start();
c.start();
}
}
leetcode191
int num = 0;
String s = Integer.toBinaryString(n);
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i)=='1') num++;
}
return num;
生产者消费者模型
hamburger类
HLS
用wait记得抛线程异常。
消费者consumer