目录
前言
周总结:
对下一周的规划:
Java
继承Thread类实现多线程
实现Runnable接口实现多线程
两种实现继承方式的区别
Thread类的相关方法
线程的生命周期
线程的同步与死锁
线程的通信
vju
简单搜索&&进阶搜索 - Virtual Judge
简单搜索&&进阶搜索 - Virtual Judge
简单搜索&&进阶搜索 - Virtual Judge
cf
Problem - B - Codeforces
这一周学习了几个有点东西的东西:IDA*,A*,状压dp,不熟,得多巩固巩固。java的第一遍系统地学习已经学完了。打了两场cf,经验就是不要死磕一个题,这毛病也不知道什么时候能改,写题的经验还是少了,写题方法也还没有成形,得浅学一下猜结论(不然嘎嘎写都写不了)。
学习mysql和maven,巩固加强java(写牛客上面的题目),聊天室的项目设计思路下周三之前得写出来,然后就是对项目的一个基本框架要搭起来,一边巩固java、mysql、maven一边写项目,学与练同时进行,对蓝桥杯的练习(这不能忘),周五之前得写完学习总结。
示例代码如下:
public class Main {
public static void main(String[] args) {
Thread t0=new TsetThread();
t0.start();
System.out.println("___________");
System.out.println("___________");
System.out.println("___________");
}
}
public class TsetThread extends Thread {
public void run(){
System.out.println("多线程运行的代码");
for(int i=0;i<5;i++){
System.out.println("这是多线程的逻辑代码"+i);
}
}
}
注意:多线程是异步处理并行状态互不相干,就是在执行t0.start的时候也会执行下面三个输出语句。
主要代码:
继承Thread类,重写run方法。
public class ***** extends Thread {
public void run(){
........
}
}
启动线程。
Thread t0=new TsetThread();
t0.start();
示例代码如下:
public class TestRunnable implements Runnable{
public void run() {
System.out.println("Runnable多线程运行的代码");
for (int i = 0; i < 5; i++) {
System.out.println("Runnable这是多线程的逻辑代码" + i);
}
}
}
public class Main {
public static void main(String[] args) {
Thread t0=new Thread(new TestRunnable());
t0.start();
System.out.println("___________");
System.out.println("___________");
System.out.println("___________");
}
}
主要代码如下:
public void run() {
。。。。
}
Thread t0=new Thread(new TestRunnable());
t0.start();
注意:一般使用实现接口的方式来实现多线程。
示例代码如下:
public class TestRunnable implements Runnable{
int count=0;
public void run() {
System.out.println(Thread.currentThread().getName()+"Runnable多线程运行的代码");
for (int i = 0; i < 5; i++) {
count++;
System.out.println(Thread.currentThread().getName()+"Runnable这是多线程的逻辑代码" + count);
}
}
}
public class Main {
public static void main(String[] args) {
/* Thread t0=new Thread(new TestRunnable());
t0.start();*/
Runnable run=new TestRunnable();
Thread t4=new Thread(run,"11");
t4.start();
Thread t5=new Thread(run,"22");
t5.start();
System.out.println("___________");
System.out.println("___________");
System.out.println("___________");
}
}
结果如下(这就是多线程共享一个资源,在这段代码里面,共享的资源是run实例):
示例代码如下:
public class Test1 {
public static void main(String[] args){
TsetRun run0=new TsetRun();
TsetRun run1=new TsetRun();
Thread t0=new Thread(run0);
Thread t1=new Thread(run1);
// t0.setName("线程t0");
t0.start();
t1.start();
System.out.println(t0.getName());
System.out.println(t1.getName());
System.out.println("___________1");
System.out.println("___________2");
System.out.println("___________3");
}
}
class TsetRun implements Runnable{
int count=0;
public void run() {
System.out.println(Thread.currentThread().getName()+"Runnable多线程运行的代码");
for (int i = 0; i < 5; i++) {
count++;
System.out.println(Thread.currentThread().getName()+"Runnable这是多线程的逻辑代码" + count);
}
}
}
主要代码如下:
获取一个名字,如果没有指定名称,系统会默认名称,如:Thread-0
System.out.println(t0.getName());
System.out.println(t1.getName());
指定线程名称
t0.setName("线程t0");
注意:优先级就是哪一个线程会大概率被优先执行,优先级用数字1~10表示,数字越大,优先级越高,如果没有设置默认的优先级是5。
主要代码:
t0.getPriority:获取t0的优先级
System.out.println("t0的优先级;"+t0.getPriority());
将t0的优先级设置成1.
t0.setPriority(1);
注意:优先级只能增大概率,既然是概率,那就不一定。
注意:多线程共享资源的时候,一个线程在执行一个方法还没有完毕时就会有另外的线程来执行这个方法,这就出现了多线程的安全问题。
为了让多线程执行方法时先让一个线程先执行完再执行另一个线程,所以有了解决方法线程的同步。
直接在方法中加上 synchronized
示例代码如下:
public class Test1 {
public static void main(String[] args){
Acount a=new Acount();
User u_weixin=new User(a,2000);
User u_zhifubao=new User(a,2000);
Thread weixin=new Thread(u_weixin,"微信");
Thread zhifubao=new Thread(u_zhifubao,"支付宝");
weixin.start();
zhifubao.start();
}
}
class Acount{
public static int money=3000;
public synchronized void drawing(int m) {
String name = Thread.currentThread().getName();
if (money < m) {
System.out.println(name + "操作:账户金额不足" + money);
} else {
System.out.println(name + "操作:账户原有金额:" + money);
System.out.println(name + "操作:取款金额:" + m);
money = money - m;
System.out.println(name + "操作:账号取款后余额:" + money);
}
}
}
class User implements Runnable{
Acount acount;
int money;
public User(Acount acount,int money){
this.acount=acount;
this.money=money;
}
public void run(){
acount.drawing(money);
}
}
在没加synchronized前:
在加synchronized后:
注意:上诉三个方法只能用在有同步锁的方法里面。
示例代码如下:
public class Test1 {
public static void main(String[] args){
Acount a=new Acount();
User u_weixin=new User(a,2000);
User u_zhifubao=new User(a,2000);
Thread weixin=new Thread(u_weixin,"微信");
Thread zhifubao=new Thread(u_zhifubao,"支付宝");
weixin.start();
zhifubao.start();
}
}
class Acount{
public static int money=3000;
public synchronized void drawing(int m,Acount a) {
String name = Thread.currentThread().getName();
if(name.equals("支付宝")){
try {
a.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (money < m) {
System.out.println(name + "操作:账户金额不足" + money);
} else {
System.out.println(name + "操作:账户原有金额:" + money);
System.out.println(name + "操作:取款金额:" + m);
money = money - m;
System.out.println(name + "操作:账号取款后余额:" + money);
}
}
}
class User implements Runnable{
Acount acount;
int money;
public User(Acount acount,int money){
this.acount=acount;
this.money=money;
}
public void run(){
acount.drawing(money,acount);
}
}
运行结果如下:
核心代码如下:
表示遇到支付宝的操作就停止。
if(name.equals("支付宝")){
try {
a.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
今天是状压专场啊!!!
分析:第一眼bfs,第二眼,不对,没有那么简单,它加了条件,所以来了新的知识点——状态压缩。
二进制状态压缩:对于只由0和1组成的数字排列,可以把它转换成相对应的十进制,用int来表示一个状态。然后把它存放在一个记录数组中的第三维,在这个题目中为了方便记录钥匙的拿到和使用情况。
代码如下:
#include
它与普通bfs不同的地方在这里:
if(mp[tail.x][tail.y]>='A'&&mp[tail.x][tail.y]<='J'&&((tail.ys&(1<<(mp[tail.x][tail.y]-'A')))==0))
continue;
else if(mp[tail.x][tail.y]>='a'&&mp[tail.x][tail.y]<='j')
tail.ys|=1<<(mp[tail.x][tail.y]-'a');
它这里的原理就是通过第三维来判断拿到的钥匙,也就是说用二进制判断拿到的钥匙的状态。
分析:
这是一个经典的旅行商问题,但是和之前的那个旅行商问题不一样的是现在这个旅行商问题它多加了一个条件:每条路最多可以走两次。一开始死磕二进制,发现不行,每条路最多走两次,那么就会存在3种情况,不走这条路那就是0次,走一次那就是1次,最多走两次那就是2次。所以蹦出来来了三进制,先求出可能的状态(也就是我下面代码的三进制数组,我直接枚举出来了),dp[ i] [ j]表示在状态 所有i 下到达 j 点的花费。那么可以推出在达到 i 之前的状态,然后枚举前状态达到的位置,对当前状态求出最小值。
代码如下:
#include
#include
#include
int sjz[11]={1,3,9,27,81,243,729,2187,6561,19683,59049};
int n,m;
int vis[60005][20];
int map[20][20];
int dp[60005][20];
int Max=0x3f3f3f3f;
void db()
{
int t;
for(int i=0;i
关键代码:
for(int i=0;i
注意:它这里一个状压,一个dp,都属于难理解的点,实现起来不难,但是一定好好理解。灵活运用(比如从二进制转成三进制)。
分析:
这题看见的时候,我就知道状压又来了,它嘎嘎熟悉(没觉得吗?),都是钥匙都要开门,这不就和我写的第一个状压的题目差得不?所以还是那个想法,用二进制表示它钥匙开门的状态,然后那一串二进制代码转换成十进制来判断。
代码如下:
#include
主要代码如下:
if( (!(tail.key & (1<
这不是嘎嘎一样?
分析:这个题,第一眼看,真简单,写了之后,我真拉。我开始的想法找出的规律是累加求前缀和,然后二分搜索比较,,,,,,但是它,,爆内存,然后就一直卡在这里了,后来学长说这个题可以直接猜结论。。。。我。。然后就是下面这个代码了。
代码如下:
#include
#include
#include
int main()
{
int t;
long long n,m;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
m=sqrt(n);
if(m*m==n)
m--;
printf("%lld\n",m);
}
}
ps:它真的就那么几行代码。。。。。。。。