创作赢红包Java多线程:synchronized锁方法块
Posted Java程序员老张
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创作赢红包Java多线程:synchronized锁方法块相关的知识,希望对你有一定的参考价值。
synchronized同步代码块 用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法执行一个较长时间的任务,那么B线程必须等待比较长的时间。这种情况下可以尝试使用synchronized同步语句块来解决问题。看一下例子: public class ThreadDomain18
public void doLongTimeTask() throws Exception
for (int i = 0; i < 100; i++)
System.out.println(
"nosynchronized threadName = " + Thread.currentThread().getName() + ", i = " + (i + 1));
System.out.println();
synchronized (this)
for (int i = 0; i < 100; i++)
System.out.println(
"synchronized threadName = " + Thread.currentThread().getName() + ", i = " + (i + 1));
public class MyThread18 extends Thread
private ThreadDomain18 td;
public MyThread18(ThreadDomain18 td)
this.td = td;
public void run()
try
td.doLongTimeTask();
catch (Exception e)
e.printStackTrace();
public static void main(String[] args)
ThreadDomain18 td = new ThreadDomain18();
MyThread18 mt0 = new MyThread18(td);
MyThread18 mt1 = new MyThread18(td);
mt0.start();
mt1.start();
运行结果,分两部分来看:
synchronized threadName = Thread-1, i = 1 synchronized threadName = Thread-1, i = 2 nosynchronized threadName = Thread-0, i = 95 synchronized threadName = Thread-1, i = 3 nosynchronized threadName = Thread-0, i = 96 synchronized threadName = Thread-1, i = 4 nosynchronized threadName = Thread-0, i = 97 synchronized threadName = Thread-1, i = 5 nosynchronized threadName = Thread-0, i = 98 synchronized threadName = Thread-1, i = 6 nosynchronized threadName = Thread-0, i = 99 synchronized threadName = Thread-1, i = 7 nosynchronized threadName = Thread-0, i = 100 ... synchronized threadName = Thread-1, i = 98 synchronized threadName = Thread-1, i = 99 synchronized threadName = Thread-1, i = 100 synchronized threadName = Thread-0, i = 1 synchronized threadName = Thread-0, i = 2 synchronized threadName = Thread-0, i = 3 ...这个实验可以得出以下两个结论: 1、 当A线程访问对象的synchronized代码块的时候,B线程依然可以访问对象方法中其余非synchronized块的部分,第一部分的执行结果证明了这一点 2、 当A线程进入对象的synchronized代码块的时候,B线程如果要访问这段synchronized块,那么访问将会被阻塞,第二部分的执行结果证明了这一点 所以,从执行效率的角度考虑,有时候我们未必要把整个方法都加上synchronized,而是可以采取synchronized块的方式,对会引起线程安全问题的那一部分代码进行synchronized就可以了。 两个synchronized块之间具有互斥性 如果线程1访问了一个对象A方法的synchronized块,那么线程B对同一对象B方法的synchronized块的访问将被阻塞,写个例子来证明一下:
public class ThreadDomain19
public void serviceMethodA()
synchronized (this)
try
System.out.println("A begin time = " + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("A end time = " + System.currentTimeMillis());
catch (InterruptedException e)
e.printStackTrace();
public void serviceMethodB()
synchronized (this)
System.out.println("B begin time = " + System.currentTimeMillis());
System.out.println("B end time = " + System.currentTimeMillis());
写两个线程分别调用这两个方法:
public class MyThread19_0 extends Thread
private ThreadDomain19 td;
public MyThread19_0(ThreadDomain19 td)
this.td = td;
public void run()
td.serviceMethodA();
public class MyThread19_1 extends Thread
private ThreadDomain19 td;
public MyThread19_1(ThreadDomain19 td)
this.td = td;
public void run()
td.serviceMethodB();
写个main函数:
public static void main(String[] args)
ThreadDomain19 td = new ThreadDomain19();
MyThread19_0 mt0 = new MyThread19_0(td);
MyThread19_1 mt1 = new MyThread19_1(td);
mt0.start();
mt1.start();
看一下运行结果:
A begin time = 1443843271982 A end time = 1443843273983 B begin time = 1443843273983 B end time = 1443843273983看到对于serviceMethodB()方法synchronized块的访问必须等到对于serviceMethodA()方法synchronized块的访问结束之后。那其实这个例子,我们也可以得出一个结论: synchronized块获得的是一个对象锁,换句话说,synchronized块锁定的是整个对象 。 synchronized块和synchronized方法 既然上面得到了一个结论 synchronized块获得的是对象锁 ,那么如果线程1访问了一个对象方法A的synchronized块,线程2对于同一对象同步方法B的访问应该是会被阻塞的,因为线程2访问同一对象的同步方法B的时候将会尝试去获取这个对象的对象锁,但这个锁却在线程1这里。写一个例子证明一下这个结论:
public class ThreadDomain20
public synchronized void otherMethod()
System.out.println("----------run--otherMethod");
public void doLongTask()
synchronized (this)
for (int i = 0; i < 1000; i++)
System.out.println(
"synchronized threadName = " + Thread.currentThread().getName() + ", i = " + (i + 1));
try
Thread.sleep(5);
catch (InterruptedException e)
e.printStackTrace();
写两个线程分别调用这两个方法:
public class MyThread20_0 extends Thread
private ThreadDomain20 td;
public MyThread20_0(ThreadDomain20 td)
this.td = td;
public void run()
td.doLongTask();
public class MyThread20_1 extends Thread
private ThreadDomain20 td;
public MyThread20_1(ThreadDomain20 td)
this.td = td;
public void run()
td.otherMethod();
写个main函数调用一下,这里"mt0.start()"后sleep(100)以下是为了确保mt0线程先启动:
public static void main(String[] args) throws Exception
ThreadDomain20 td = new ThreadDomain20();
MyThread20_0 mt0 = new MyThread20_0(td);
MyThread20_1 mt1 = new MyThread20_1(td);
mt0.start();
Thread.sleep(100);
mt1.start();
看一下运行结果:
... synchronized threadName = Thread-0, i = 995 synchronized threadName = Thread-0, i = 996 synchronized threadName = Thread-0, i = 997 synchronized threadName = Thread-0, i = 998 synchronized threadName = Thread-0, i = 999 synchronized threadName = Thread-0, i = 1000 ----------run--otherMethod证明了我们的结论。为了进一步完善这个结论,把"otherMethod()"方法的synchronized去掉再看一下运行结果:
... synchronized threadName = Thread-0, i = 16 synchronized threadName = Thread-0, i = 17 synchronized threadName = Thread-0, i = 18 synchronized threadName = Thread-0, i = 19 synchronized threadName = Thread-0, i = 20 ----------run--otherMethod synchronized threadName = Thread-0, i = 21 synchronized threadName = Thread-0, i = 22 synchronized threadName = Thread-0, i = 23 ..."otherMethod()"方法和"doLongTask()"方法中的synchronized块异步执行了 将任意对象作为对象监视器 总结一下前面的内容: 1、synchronized同步方法 (1)对其他synchronized同步方法或synchronized(this)同步代码块呈阻塞状态 (2)同一时间只有一个线程可以执行synchronized同步方法中的代码 2、synchronized同步代码块 (1)对其他synchronized同步方法或synchronized(this)同步代码块呈阻塞状态 (2)同一时间只有一个线程可以执行synchronized(this)同步代码块中的代码 前面都使用synchronized(this)的格式来同步代码块,其实 Java还支持对"任意对象"作为对象监视器来实现同步的功能 。这个"任意对象"大多数是 实例变量 及 方法的参数 ,使用格式为synchronized(非this对象)。看一下将任意对象作为对象监视器的使用例子:
public class ThreadDomain21
private String userNameParam;
private String passwordParam;
private String anyString = new String();
public void setUserNamePassword(String userName, String password)
try
synchronized (anyString)
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis() + " 进入同步代码块");
userNameParam = userName;
Thread.sleep(3000);
passwordParam = password;
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在 " + System.currentTimeMillis() + " 离开同步代码块");
catch (InterruptedException e)
e.printStackTrace();
写两个线程分别调用一下:
public class MyThread21_0 extends Thread
private ThreadDomain21 td;
public MyThread21_0(ThreadDomain21 td)
this.td = td;
public void run()
td.setUserNamePassword("A", "AA");
public class MyThread21_1 extends Thread
private ThreadDomain21 td;
public MyThread21_1(ThreadDomain21 td)
this.td = td;
public void run()
td.setUserNamePassword("B", "B");
写一个main函数调用一下:
public static void main(String[] args)
ThreadDomain21 td = new ThreadDomain21();
MyThread21_0 mt0 = new MyThread21_0(td);
MyThread21_1 mt1 = new MyThread21_1(td);
mt0.start();
mt1.start();
看一下运行结果:
线程名称为:Thread-0在 1443855101706 进入同步代码块 线程名称为:Thread-0在 1443855104708 离开同步代码块 线程名称为:Thread-1在 1443855104708 进入同步代码块 线程名称为:Thread-1在 1443855107708 离开同步代码块这个例子证明了: 多个线程持有"对象监视器"为同一个对象的前提下,同一时间只能有一个线程可以执行synchronized(非this对象x)代码块中的代码 。 锁非this对象具有一定的优点:如果在一个类中有很多synchronized方法,这时虽然能实现同步,但会受到阻塞,从而影响效率。但如果同步代码块锁的是非this对象,则synchronized(非this对象x)代码块中的程序与同步方法是异步的,不与其他锁this同步方法争抢this锁,大大提高了运行效率。 注意一下"private String anyString = new String();"这句话,现在它是一个全局对象,因此监视的是同一个对象。如果移到try里面,那么对象的监视器就不是同一个了,调用的时候自然是异步调用,可以自己试一下。 最后提一点,synchronized(非this对象x),这个对象如果是实例变量的话,指的是对象的引用, 只要对象的引用不变,即使改变了对象的属性,运行结果依然是同步的 。 细化synchronized(非this对象x)的三个结论 synchronized(非this对象x)格式的写法是将x对象本身作为对象监视器,有三个结论得出: 1、当多个线程同时执行synchronized(x)同步代码块时呈同步效果 2、当其他线程执行x对象中的synchronized同步方法时呈同步效果 3、当其他线程执行x对象方法中的synchronized(this)代码块时也呈同步效果 第一点很明显,第二点和第三点意思类似,无非一个是同步方法,一个是同步代码块罢了,举个例子验证一下第二点:
public class MyObject
public synchronized void speedPrintString()
System.out.println("speedPrintString__getLock time = " + System.currentTimeMillis() + ", run ThreadName = " + Thread.currentThread().getName());
System.out.println("----------");
System.out.println("speedPrintString__releaseLock time = " + System.currentTimeMillis()+ ", run ThreadName = " + Thread.currentThread().getName());
ThreadDomain24中持有MyObject的引用:
public class ThreadDomain24
public void testMethod1(MyObject mo)
try
synchronized (mo)
System.out.println("testMethod1__getLock time = " + System.currentTimeMillis() + ", run ThreadName = " + Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("testMethod1__releaseLock time = " + System.currentTimeMillis() + ", run ThreadName = " + Thread.currentThread().getName());
catch (InterruptedException e)
e.printStackTrace();
写两个线程分别调用"
speedPrintString()
"方法和"
testMethod1(MyObject mo)
"方法:
public class MyThread24_0 extends Thread
private ThreadDomain24 td;
private MyObject mo;
public MyThread24_0(ThreadDomain24 td, MyObject mo)
this.td = td;
this.mo = mo;
public void run()
td.testMethod1(mo);
public class MyThread24_1 extends Thread
private MyObject mo;
public MyThread24_1(MyObject mo)
this.mo = mo;
public void run()
mo.speedPrintString();
写一个main函数启动这两个线程:
public static void main(String[] args)
ThreadDomain24 td = new ThreadDomain24();
MyObject mo = new MyObject();
MyThread24_0 mt0 = new MyThread24_0(td, mo);
MyThread24_1 mt1 = new MyThread24_1(mo);
mt0.start();
mt1.start();
看一下运行结果:
testMethod1__getLock time = 1443855939811, run ThreadName = Thread-0 testMethod1__releaseLock time = 1443855944812, run ThreadName = Thread-0 speedPrintString__getLock time = 1443855944812, run ThreadName = Thread-1 ---------- speedPrintString__releaseLock time = 1443855944812, run ThreadName = Thread-1看到"speedPrintString()"方法必须等待"testMethod1(MyObject mo)"方法执行完毕才可以执行,没有办法异步执行,证明了第二点的结论。第三点的验证方法类似,就不写代码证明了。
创作赢红包项目信息分析表
项目的背景和问题 | 项目背景: 很多父母都希望他们的孩子成为优秀的人,但是在实践中,他们的教育方式往往会出现一些与期望不符的情况。这可能是因为这些父母很大程度上是按照自己的父母的教育方式来教育孩子的,这导致一些不太好的方式被沿袭和流传下来。,举个例子来说,一些父母可能会采用体罚来惩罚孩子的错误行为,这种方式在当今社会已经不被认可,因为它不仅可能导致身体伤害,还可能造成心理创伤。另外,一些父母可能会采取强制孩子按照自己的期望去选择职业或学习方向,这也不利于孩子的自我发展和独立思考能力的培养。在某些社会和文化环境中,父母可能会更加强调孩子的功利价值,而忽视孩子的情感和心理健康。 父母们可能受到媒体的影响,以及周围人的看法和期望,而不是真正了解孩子的需求和个性。对于上述问题,很多父母可能已经发现自己在教育方式上可能出现了问题,但是受限于自身的眼界和知识储备,无法在和孩子的日常交流上有更加高效的方式 问题: 1、家长们缺乏家庭教育知识和经验,不知道如何与孩子有效沟通和教育孩子。 2、有时候父母可能已经意识到问题了,但是在平时的教育中容易忘记素质教育,而回到之前的教育方式从而对孩子造成不好的影响 清晰而准确的描述出问题以及问题所处的背景、行业等,不能空乏。 |
解决方案 | 我们可以开发一个在线家庭教育平台,为家长和孩子提供家庭教育指导师的指导性帮助,帮助家长更好地与孩子沟通和教育孩子,提高家庭教育质量。 可以建立一个针对家长和孩子的个性化档案系统,根据孩子的年龄、兴趣、学习能力等信息,为家长提供相关的教育资源和建议。 此外,可以建立一个社区或论坛,让家长之间可以互相交流分享经验和教育方法,从而让他们有机会互相帮助和学习。家庭教育指导师可以在社区中与家长互动,回答家长的问题,提供咨询和建议。 最后,利用数据分析和人工智能技术,可以根据家长和孩子的需求和反馈,提供个性化的建议和推荐,帮助家长更好地选择适合自己孩子的教育方式。同时,提供孩子对本项目的评价渠道,也可以单方面要求指导师与其进行沟通交流。 (增加家长的家庭教育知识与经验,同时改善亲子关系,并为家长提供孩子长远的个性化教育指导与人生规划) 针对问题,提出有效可行的解决方案。 |
产品、服务 | 平台功能包括: 1.一对一指导:提供线上专业的一对一家庭教育咨询和指导,帮助家长解决教育问题,提供有效的教育策略和方法。也可以通过在线沟通工具(如:微信),方便家长和指导师进行交流和沟通。 2.家庭教育资源库:提供包括教育视频、教育文章等,帮助家长更好地了解和掌握家庭教育知识。并通过邀请其他相关机构、商家入驻的方式丰富其他家庭教育相关资源。 3.家长社区:创建家长社区,让家长们分享教育经验和教育资源,共同交流和解决教育问题.(类似于贴吧的文字交流平台) 4.定期活动:定期举办家庭教育活动,例如夏令营,线下沙龙活动,增强与家长之间的互动交流, 5.目标定制:了解家长想法:孩子受环境和家长影响最深,目标能否进行,很大程度上取决于家长的态度;尊重孩子意愿:孩子是目标的制定者,也是执行目标的主体。我们的任务是对孩子给予合适的引导和专业知识的辅助,细化目标并增强目标的可行性,提升孩子对未来的自信心。 根据方案,你所提供的有价值的产品或者服务。 |
客户和用户画像 | 在这个家庭教育指导平台中,主要的用户群体是有孩子的家长,特别是那些希望提高家庭教育质量、但缺乏足够知识和经验的家长。具体的用户画像包括:
客户是出钱购买你产品或者服务的人;用户是使用你产品或者服务的人。画像简单明了描述说用户、客户的特点,通常可以借用社会共识描述,例如28-33岁的城市白领。客户和用户有时是相同的。 |
市场分析 | 市场规模与增长性: 随着社会对教育水平的不断提升,家长对子女教育的重视程度也越来越高。而随着家庭教育市场的不断发展,这个市场的规模也在不断扩大。根据相关数据显示,全球家庭教育市场规模已经超过了1000亿美元,而且这个市场的年增长率高达10%以上。 我国3-18岁青少年儿童基数庞大,家庭教育市场空间潜力巨大,教育部发布的2021年教育事业统计数据显示,2021年我国处于幼儿园、小学及中学阶段的在校生规模近2.5亿,其中幼儿园在园幼儿4805.21万,小学在校生1.08亿人,初中在校生5018.44万人,普通高中在校生2605.03万,中等职业学校在校生1311.81万人。 市场竞争状况: 目前市场上的致力于情商与家庭教育的机构有更多,如6q教育 智乐星球 小象学院等等,这些机构基本上都用于专属于自己的直播线上教学平台。但是这些线上平台都是专属于单一机构授课使用,服务不全面,运维成本高,宣传效果差。我们的平台可以提供多样化服务,如:线上专业家庭指导师一对一指导,丰富的家庭教育资源和教材,还有专门的家长社区可以分享教育经验和教育资源,同时可以通过社区找到志同道合的家长一起预约线下的亲子活动或者课程。 目标用户群体: 儿童是民族的未来与希望,儿童的健康成长不仅影响家庭的前途与命运,更关乎国家的发展与前景,而儿童的第一个课堂以及影响儿童成长的重要“教室”,无疑就是——家庭。 当代家庭投入在孩子教育和成长上的时间、精力、金钱都比以前增加了很多。但是,孩子的成长问题却也比以前更多了,这也成了家庭幸福的阻碍。 该平台的目标用户群体是具有子女的家长,尤其是那些需要帮助和指导的家长。这些家长大多数都拥有一定的教育背景,但是对于如何教育孩子和如何和孩子沟通等方面可能存在一定的困惑和挑战。 市场机会: 家庭教育市场是一个处于不断发展中的市场,同时也存在着巨大的机会。随着科技的发展和数字化教育的兴起,家庭教育市场的发展空间更加广阔。同时,随着年轻一代成为主流的教育消费者,家庭教育市场的消费群体也将会不断扩大。 市场有多大(注意市场是指你的产品能覆盖的空间,可以是存量和有逻辑的增量。)?目前有哪些产品或服务正在满足市场?市场的机会在哪里? |
营销计划和策略 | 对于招揽客户的家庭教育机构一方,我们提供客户资源和流量支持。有能力的机构可以通过上传自己教师信息,租借广告位等提高自己的竞争力,以便更高效地匹配到合适的客户,减少沟通成本。 对于需求方如家长,我们平台提供大量家庭教育机构的信息,同时提供筛选操作,可以让家长快速的找到时间安排,教学质量和价格档次都合适的机构,省时,省心,省钱。 如何保证客户选择你的产品?他们不仅要知道你的产品,还要知道如何获得,还要知道选择你的理由。策略是一个整体战略的方案集合抽象;计划是阶段性明确性的安排。 |
已有基础 | 产品、理论研究、人力资源、市场分析等等参与商业运营各要素目前已经做了哪些事?形成了哪些成果?造就了怎样的态势? |
团队情况 | 人力资源组织情况。每个岗位都是协作机制的节点,他们由那些人负责,是否恰当? |
项目特点 | 这个家庭教育指导平台有以下几个特点,这些特点可以提高平台的竞争力:
综合来看,该平台的专业性、个性化服务和数据化服务能够提供更为优质的教育指导服务,同时,多元化的教育内容和丰富的用户社区也能够提高用户黏性和用户满意度,从而增加平台的竞争力。 和其他同类项目相比,在解决方案、提供的产品和服务、提供的方式、团队、技术手段、商业模式要素(生产、服务、营销)等各方面有哪些不同? 注意:如果核心的商业模式要素和别人一样,就不是特点;如果比别人还差,就没有存在的必要;描述时不能空泛,一定要简练准确明了; 项目特点往往是创新性的体现,往往是竞争优势 |
盈利模式 |
你到底挣的是什么钱?要注意几个问题: 1.一定要说清楚,挣得是什么钱?例如是产品的销售或者租金 2.不要什么钱都挣,你可以想很多,但要内聚 3.初创时还没挣到钱,这个时候论证逻辑是关键 4.能挣多少,是算出来的,不是拍脑袋出来的 5.挣的钱必须是在商业模型基础上完成的(例如:不是熟人大单偶然完成的) |
财务分析 | 初创的项目没办法财务分析,可给出合理财务假设,有逻辑链条推导,形成财务销售。 例如产品或服务定价可参考市场价,推广的数据可参考同等状况下其他项目的……,按推广计划分析 注意盈利模式和财务分析是看你的经济价值,可信可行是对价值的有效支撑。 |
以上是关于创作赢红包Java多线程:synchronized锁方法块的主要内容,如果未能解决你的问题,请参考以下文章