2021年3月13日星期六

第一个鸿蒙程序Hello Word

DevEco Studio介绍

HUAWEI DevEco Studio(以下简称DevEco Studio)是基于IntelliJ IDEA Community开源版本打造,面向华为终端全场景多设备的一站式集成开发环境(IDE),为开发者提供工程模板创建、开发、编译、调试、发布等E2E的HarmonyOS应用开发服务。通过使用DevEco Studio,开发者可以更高效的开发具备HarmonyOS分布式能力的应用,进而提升创新效率。

下载与安装软件

登录HarmonysOS应用开发门户,点击右上角注册按钮,注册开发者帐号,注册指导参考注册华为开发者联盟帐号。如果已有华为开发者联盟帐号,请直接点击登录按钮。

DevEco Studio下载跟安装:

https://developer.harmonyos.com/cn/develop/deveco-studio

DevEco Studio的编译构建依赖JDK,DevEco Studio预置了Open JDK,版本为1.8,安装过程中会自动安装JDK。

下载和安装Node.js:

https://nodejs.org/zh-cn/download/

设置npm仓库

为了提升下载JS SDK时,使用npm安装JS依赖的速度,建议在命令行工具(Mac系统为"终端"工具)中执行如下命令,重新设置npm仓库地址。

npm config set registry https://repo.huaweicloud.com/repository/npm/

用DevEco Studio新建一个项目

安装好工具跟node.js之后,打开DevEco Studio,首页如下图所示:

DevEco Studio首页

然后点击Create HarmonyOS Project按钮新建一个项目,进入选择模版界面,在模版界面下选择Phone跟Empty Feature Ability(Java),这里需要选择Phone大家很好理解,代表手机开发,但是为什么选择Empty Feature Ability,后续的章节我们会介绍Ability是什么?

选择模版

选择了模版之后,点击Next按钮,进入配置项目界面,这个页面有四个输入框,依次是:项目名称、包名、项目保存路径、编译API版本!做个Android开发的朋友对这些项目配置信息应该都很熟悉了,这里就不做过多介绍了。

项目配置

项目配置信息这里我就用系统默认的了,点击Finish按钮,一个新的项目就创建成功啦。

项目目录结构

使用模拟器运行

目前为止市场上还没有带鸿蒙操作系统的手机,现在大家只能用模拟器调试运行,点击菜单栏工具:Tools->HVD Manager,这个时候会打开浏览器验证您的华为开发者账号,验证完成之后会打开模拟器设备管理界面,我们点击Phone,选择只有一款模拟器,华为P40手机,双击P40手机所在的行,就会启动模拟器。

选择设备

启动模拟器之后,在开发工具右边就有一个小手机啦,然后点击工具栏上的运行按钮运行按钮,选择我们的模拟器运行,运行之后模拟器上显示一行文字"Hello Word",第一个鸿蒙程序就此诞生啦。

运行Hello Word

总结

以上所有的内容在鸿蒙操作系统官网都有,大家可以访问官网学习更多知识,当然也可以关注我的公众号,后期会一直更新,我会一直学习鸿蒙开发,然后把内容总结发布到公众号。官方开发者官网如下:

https://www.harmonyos.com/cn/develop

如果你之前是Android开发者,学习鸿蒙开发上手会很快,主要有以下几点:

  1. 开发工具基于IntelliJ IDEA Community,跟Android Studio是一个爸爸
  2. 开发语言支持Java
  3. 项目结构,还有代码风格跟Android很像,反正我第一次看到这个项目结构的时候很容易看懂。

如果你想第一时间看我的后期文章,扫码关注公众号,长期推送Android开发文章、最新动态、开源项目,让你各种涨姿势。

  Android开发666 - 安卓开发技术分享    扫描二维码加关注

Android开发666









原文转载:http://www.shaoqun.com/a/623657.html

跨境电商:https://www.ikjzd.com/

易趣:https://www.ikjzd.com/w/210

递四方:https://www.ikjzd.com/w/1066


DevEcoStudio介绍HUAWEIDevEcoStudio(以下简称DevEcoStudio)是基于IntelliJIDEACommunity开源版本打造,面向华为终端全场景多设备的一站式集成开发环境(IDE),为开发者提供工程模板创建、开发、编译、调试、发布等E2E的HarmonyOS应用开发服务。通过使用DevEcoStudio,开发者可以更高效的开发具备HarmonyOS分布式能力的应
e邮包:https://www.ikjzd.com/w/594.html?source=tagwish
new old stock:https://www.ikjzd.com/w/2341
r标:https://www.ikjzd.com/w/1070
孟晚舟背负16项条约获得保释,特朗普却这样表态!:https://www.ikjzd.com/home/12929
推荐!亚马逊6大家居热销品类!:https://www.ikjzd.com/home/96799
超级干货:11个用于营销分析的最佳Facebook小工具!:https://www.ikjzd.com/home/14636

男人有4种异常出汗?别怀疑,是身体出问题了!

核心提示:出汗是人体正常的生理反应,也是保证体温恒定的关键方式之一。在夏天流汗是很正常的,但如果到了寒冷的季节,或是某些特定时刻,还是大汗不止,此时就要当心了,很可能预示着身体出了问题。

出汗是人体正常的生理反应,也是保证体温恒定的关键方式之一。在夏天流汗是很正常的,但如果到了寒冷的季节,或是某些特定时刻,还是大汗不止,此时就要当心了,很可能预示着身体出了问题,男性朋友尤其要注意。

男人四种出汗异常需警惕

1、到半夜冒汗不止

有的人晚上入睡会流汗,醒来后就不流,这是典型的盗汗表现。

大部分的盗汗都是阴虚引起,从中医角度看,人阴虚则阳亢,这一种人一般都伴有口干舌燥、情绪不稳定、失眠等症状。

支招:

多吃雪梨、百合、蜂蜜等食物滋阴去燥,像牛羊肉、葱姜蒜等热性食物少吃点。

平时可以用麦冬、沙参、西洋参等泡水饮。

2、头颈部经常出汗

头汗是指患者仅仅在头部或脖子这一块出汗较多。

出现这种症状的原因,大部分是上焦火旺,或中焦湿热,或疾病所致的虚火过盛。


支招:

假如患者还经常出现口臭、上腹饱胀、没食欲,则怀疑是积食,建议控制进食量、保证饮食的清淡。

也可以用麦芽30g,独脚金15g水煎服用。

3、出汗不分时间季节

有些男性即便在冬天,没有运动,稍微走动一下就出汗。

这种情况是"自汗",大多因肺气虚弱、卫阳不固、津液外泄。

自汗患者体质通常偏虚,容易感冒,动一动就会出汗,干不了长时间的体力活。

有一些气虚的患者会伴有阴虚。

除了体虚外,患者还可能有手脚心发热,心烦易怒,盗汗等表现。

支招:

如果是气虚型的自汗患者,调理还是以食疗为主,平时不妨多吃山药、黄芪、大枣等补气中药材。

如果是气阴两虚,调养就要注重清火滋阴、益气养阴,可食用百合、银耳、枸杞、洋参等食材进行调理。

4、隐私部位出汗原因多

阴 囊潮湿是男科常见问题之一,主要指生殖器及周围皮肤常常出汗,并带有臊臭味。

有一些疾病会诱发阴 囊潮湿,如精索静脉曲张、阴 囊湿疹、慢性前列腺炎、糖尿病等。


此外,长期精神紧绷、情绪大起大落、患慢性消化系统疾病、内分泌失调、有新陈代谢障碍的人也比较容易得这种病。

生活环境潮湿、经常穿紧身内裤等都会使阴 囊发痒潮湿。

支招:

男性若患上这种病,情绪不必过于紧张,避免因情绪而使病情加重。


另外,平日饮食要清淡,戒酒戒烟,避免辛辣刺激等食物。

平时多穿宽松的棉质内裤,少穿紧身牛仔裤。

同时要注意个人卫生,避免经常搔抓,尤其是体型肥胖者。


原文转载:http://health.shaoqun.com/a/202099.html

跨境电商:https://www.ikjzd.com/

跨境通电子商务网站:https://www.ikjzd.com/w/1329

indiegogo:https://www.ikjzd.com/w/265


核心提示:出汗是人体正常的生理反应,也是保证体温恒定的关键方式之一。在夏天流汗是很正常的,但如果到了寒冷的季节,或是某些特定时刻,还是大汗不止,此时就要当心了,很可能预示着身体出了问题。 出汗是人体正常的生理反应,也是保证体温恒定的关键方式之一。在夏天流汗是很正常的,但如果到了寒冷的季节,或是某些特定时刻,还是大汗不止,此时就要当心了,很可能预示着身体出了问题,男性朋友尤其要注意。男人四种出汗异常
敦煌网:https://www.ikjzd.com/w/189
usps:https://www.ikjzd.com/w/513
淘粉吧返利:https://www.ikjzd.com/w/1725
是没订单所以才没事情做,还是没做事情所以才没有订单?:https://www.ikjzd.com/home/20560
海外买家要发票,不会开票怎么办?亚马逊这款神器,帮你自动开票!:https://www.ikjzd.com/home/134073
亚马逊PPC广告能做竞价吗?怎样通过竞价来盈利?:https://www.ikjzd.com/home/110240

2021年3月12日星期五

一文读懂Java多线程原理

前言

线程池,故名思意,就是一个存放线程的池子,学术一点的说法,就是一组存放线程资源的集合。为什么有线程池这一概念地产生呢?想想以前我们都是需要线程的时候,直接自己手动来创建一个,然后执行完任务我们就不管了,线程就是我们执行异步任务的一个工具或者说载体,我们并没有太多关注于这个线程自身生命周期对于系统或环境的影响,而只把重心放在了多线程任务执行完成的结果输出,然后目的达到了,但是真正忽略了线程资源的维护和监控等问题。随着大型系统大量多线程资源的使用,对多线程疏于重视、维护和管理而对资源占用和拉低性能的影响逐渐扩大,才引起了人们的思考。

多线程的创建和销毁在多线程的生命周期中占有很大比重,这一部分其实很占用资源和性能,如果使用线程来执行简单任务,而因为线程本身的维护成本已经超出任务执行的效益,这是得不偿失的,于是就产生了线程池。通过使用线程池,将线程的生命周期管控起来,同时能够方便地获取到线程、复用线程,避免频繁地创建和销毁线程带来额外性能开销,这大概就是线程池引入的背景和初衷吧。

一、多线程创建方式

1.1、继承Thread类创建线程类

1.实现步骤

定义一个继承Thread类的子类,并重写该类的run()方法;

创建Thread子类的实例,即创建了线程对象;

调用该线程对象的start()方法启动线程。

2.核心代码

`class SomeThead extends Thraad { public void run() { //do something here
}
}

public static void main(String[] args){SomeThread oneThread = new SomeThread();
//启动线程
oneThread.start();}`

1.2、实现Runnable接口创建线程类

1.实现步骤

定义Runnable接口的实现类,并重写该接口的run()方法;

创建Runnable实现类的实例,并以此实例作为Thread的target对象,即该Thread对象才是真正的线程对象。

2.核心代码

class SomeRunnable implements Runnable { public void run() { //do something here } } Runnable oneRunnable = new SomeRunnable(); Thread oneThread = new Thread(oneRunnable); oneThread.start();

1.3、通过Callable和Future创建线程

1.实现步骤

创建Callable接口的实现类,并实现call()方法,改方法将作为线程执行体,且具有返回值。

创建Callable实现类的实例,使用FutrueTask类进行包装Callable对象,FutureTask对象封装了Callable对象的call()方法的返回值

使用FutureTask对象作为Thread对象的target创建并启动新线程

调用FutureTask对象的get()方法获取子线程执行结束后的返回值。

2.核心代码

`//1.创建Callable接口的实现类,并实现call()方法public class SomeCallable01 implements Callable {@Overridepublic Integer call() throws Exception {int i = 0;for(;i<10;i++){System.out.println(Thread.currentThread().getName()+" "+i);}return i;}

public static void main(String[] args) {	//2.创建Callable实现类的实例 SomeCallable01 ctt = new SomeCallable01();  //3.使用FutrueTask类进行包装Callable对象,FutureTask对象封装了Callable对象的call()方法的返回值 FutureTask<Integer> ft = new FutureTask<>(ctt); //开启ft线程 for(int i = 0;i < 21;i++) {  System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);  if(i==20)//i为20的时候创建ft线程  {  	//4.使用FutureTask对象作为Thread对象的target创建并启动新线程   new Thread(ft,"有返回值的线程FutureTask").start();  } } //ft线程结束时,获取返回值 try {	 	//5.调用FutureTask对象的get()方法获取子线程执行结束后的返回值。  System.out.println("子线程的返回值:"+ft.get());//get()方法会阻塞,直到子线程执行结束才返回 } catch (InterruptedException e) {  e.printStackTrace(); } catch (ExecutionException e) {  e.printStackTrace(); }}复制代码

}`

二、创建线程方式的区别

1.使用继承Thread类的方式创建多线程

1)优势

编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。

2)劣势

线程类已经继承了Thread类,所以不能再继承其他父类。(有单继承的局限性)

创建多线程时,每个任务有成员变量时不共享,必须加static才能做到共享

2.使用实现Runnable类的方式创建多线程

1)优势

避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。

2)劣势

比较复杂、访问线程必须使用Thread.currentThread()方法、无返回值。

3.使用实现Callable接口的方式创建多线程

1)优势

有返回值、避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。

2)劣势

比较复杂、访问线程必须使用Thread.currentThread()方法

4.Runnable和Callable的区别

1)Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。

2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。

3)call方法可以抛出异常,run方法不可以。

4)运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果future.get()。

三、多线程调度

3.1、调度策略

时间片:线程的调度采用时间片轮转的方式 抢占式:高优先级的线程抢占CPU

3.2、Java的调度方法

1)对于同优先级的线程组成先进先出队列(先到先服务),使用时间片策略

2)对高优先级,使用优先调度的抢占式策略

3.3、线程的优先级

等级:

MAX_PRIORITY:10

MIN_PRIORITY:1

NORM_PRIORITY:5

方法:

`getPriority():返回线程优先级

setPriority(int newPriority):改变线程的优先级`

备注:

高优先级的线程要抢占低优先级的线程的cpu的执行权。但是仅是从概率上来说的,高优先级的线程更有可能被执行。并不意味着只有高优先级的线程执行完以后,低优先级的线程才执行。

四、多线程状态管理

4.1、线程睡眠---sleep

1)概述

如果我们需要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用Thread的sleep方法。

2)线程睡眠方法

在指定的毫秒数内让正在执行的线程休眠:

sleep(long millis) 在指定的毫秒数加指定的纳秒数内让正在执行的线程休眠:

sleep(long millis,int nanos)

3)代码实现

sleep是静态方法,最好不要用Thread的实例对象调用它,因为它睡眠的始终是当前正在运行的线程,而不是调用它的线程对象,它只对正在运行状态的线程对象有效。

`public class SynTest { public static void main(String[] args) { new Thread(new CountDown(),"倒计时").start(); } }

class CountDown implements Runnable{ int time = 10; public void run() { while (true) { if(time>=0){ System.out.println(Thread.currentThread().getName() + ":" + time--); try { Thread.sleep(1000); //睡眠时间为1秒 } catch (InterruptedException e) { e.printStackTrace(); } } } } }`

4)备注

Java线程调度是Java多线程的核心,只有良好的调度,才能充分发挥系统的性能,提高程序的执行效率。但是不管程序员怎么编写调度,只能最大限度的影响线程执行的次序,而不能做到精准控制。因为使用sleep方法之后,线程是进入阻塞状态的,只有当睡眠的时间结束,才会重新进入到就绪状态,而就绪状态进入到运行状态,是由系统控制的,我们不可能精准的去干涉它,所以如果调用Thread.sleep(1000)使得线程睡眠1秒,可能结果会大于1秒。

4.2、线程让步---yield

1)概述

yield()方法和sleep()方法有点相似,它也是Thread类提供的一个静态的方法,它也可以让当前正在执行的线程暂停,让出cpu资源给其他的线程。但是和sleep()方法不同的是,它不会进入到阻塞状态,而是进入到就绪状态。yield()方法只是让当前线程暂停一下,重新进入就绪的线程池中,让系统的线程调度器重新调度器重新调度一次,完全可能出现这样的情况:当某个线程调用yield()方法之后,线程调度器又将其调度出来重新进入到运行状态执行。

实际上,当某个线程调用了yield()方法暂停之后,优先级与当前线程相同,或者优先级比当前线程更高的就绪状态的线程更有可能获得执行的机会,当然,只是有可能,因为我们不可能精确的干涉cpu调度线程。

2)代码实现

public class Test1 {  public static void main(String[] args) throws InterruptedException {   new MyThread("低级", 1).start();   new MyThread("中级", 5).start();   new MyThread("高级", 10).start();  } } class MyThread extends Thread {  public MyThread(String name, int pro) {   super(name);// 设置线程的名称   this.setPriority(pro);// 设置优先级  }  @Override  public void run() {   for (int i = 0; i < 30; i++) {    System.out.println(this.getName() + "线程第" + i + "次执行!");    if (i % 5 == 0)     Thread.yield();   }  } }复制代码

3)sleep和yield的区别

①sleep方法暂停当前线程后,会进入阻塞状态,只有当睡眠时间到了,才会转入就绪状态。而yield方法调用后 ,是直接进入就绪状态,所以有可能刚进入就绪状态,又被调度到运行状态。

②sleep方法声明抛出了InterruptedException,所以调用sleep方法的时候要捕获该异常,或者显示声明抛出该异常。而yield方法则没有声明抛出任务异常。

③sleep方法比yield方法有更好的可移植性,通常不要依靠yield方法来控制并发线程的执行。

4.3、线程合并---join

1)概述

线程的合并的含义就是将几个并行线程的线程合并为一个单线程执行,应用场景是当一个线程必须等待另一个线程执行完毕才能执行时,Thread类提供了join方法来完成这个功能,注意,它不是静态方法。

简而言之:

​ 当B线程执行到了A线程的.join()方法时,B线程就会等待,等A线程都执行完毕,B线程才会执行。join可以用来临时加入线程执行。

2)线程合并方法

它有三个重载方法:

​ 当前线程等该加入该线程后面,等待该线程终止。

void join()

​ 当前线程等待该线程终止的时间最长为 millis 毫秒。

​ 如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度

void join(long millis)

​ 等待该线程终止的时间最长为 millis 毫秒 + nanos

​ 纳秒。如果在millis时间内,该线程没有执行完,那么当前线程进入就绪状态,重新等待cpu调度

void join(long millis,int nanos)

3)代码实现

public static void main(String[] args) throws InterruptedException {   yieldDemo ms = new yieldDemo();  Thread t1 = new Thread(ms,"张三吃完还剩");  Thread t2 = new Thread(ms,"李四吃完还剩");  Thread t3 = new Thread(ms,"王五吃完还剩");  t1.start();  t1.join();    t2.start();  t3.start();  System.out.println( "主线程"); }`   Thread t = new Thread(() -> { try {  Thread.sleep(1000); } catch (InterruptedException e) {  e.printStackTrace(); } r = 10;});t.start();// 让主线程阻塞 等待t线程执行完才继续执行 // 去除该行,执行结果为0,加上该行 执行结果为10t.join();log.info("r:{}", r);// 运行结果13:09:13.892 [main] INFO thread.TestJoin - r:10复制代码

4.4、设置线程的优先级

1)概述

每个线程执行时都有一个优先级的属性,优先级高的线程可以获得较多的执行机会,而优先级低的线程则获得较少的执行机会。与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的也并非没机会执行。

每个线程默认的优先级都与创建它的父线程具有相同的优先级,在默认情况下,main线程具有普通优先级。

2)涉及优先级方法

Thread类提供了setPriority(int newPriority)和getPriority()方法来设置和返回一个指定线程的优先级,其中setPriority方法的参数是一个整数,范围是1~·0之间,也可以使用Thread类提供的三个静态常量:

MAX_PRIORITY =10 MIN_PRIORITY =1 NORM_PRIORITY =5

3)代码实现

public class Test1 {   public static void main(String[] args) throws InterruptedException {    new MyThread("高级", 10).start();    new MyThread("低级", 1).start();   }  }   class MyThread extends Thread {   public MyThread(String name,int pro) {    super(name);//设置线程的名称    setPriority(pro);//设置线程的优先级   }   @Override   public void run() {    for (int i = 0; i < 100; i++) {     System.out.println(this.getName() + "线程第" + i + "次执行!");    }   }  } 复制代码

4)备注

虽然Java提供了10个优先级别,但这些优先级别需要操作系统的支持。不同的操作系统的优先级并不相同,而且也不能很好的和Java的10个优先级别对应。所以我们应该使用MAX_PRIORITY、MIN_PRIORITY和NORM_PRIORITY三个静态常量来设定优先级,这样才能保证程序最好的可移植性。

4.5、后台(守护)线程

1)概述

守护线程使用的情况较少,但并非无用,举例来说,JVM的垃圾回收、内存管理等线程都是守护线程。还有就是在做数据库应用时候,使用的数据库连接池,连接池本身也包含着很多后台线程,监控连接个数、超时时间、状态等等。

默认情况下,java进程需要等待所有线程都运行结束,才会结束,有一种特殊线程叫守护线程,当所有的非守护线程都结束后,即使它没有执行完,也会强制结束。

2)涉及方法

调用线程对象的方法setDaemon(true),则可以将其设置为守护线程。

将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。 该方法首先调用该线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException(在当前线程中)。

public final void setDaemon(boolean on)
参数:on - 如果为 true,则将该线程标记为守护线程。
抛出:
IllegalThreadStateException - 如果该线程处于活动状态。
SecurityException - 如果当前线程无法修改该线程。

3)守护线程的用途

守护线程通常用于执行一些后台作业,例如在你的应用程序运行时播放背景音乐,在文字编辑器里做自动语法检查、自动保存等功能。

java的垃圾回收也是一个守护线程。守护线的好处就是你不需要关心它的结束问题。例如你在你的应用程序运行的时候希望播放背景音乐,如果将这个播放背景音乐的线程设定为非守护线程,那么在用户请求退出的时候,不仅要退出主线程,还要通知播放背景音乐的线程退出;如果设定为守护线程则不需要了。

4.6、停止线程

1)概述

Thread.stop()、Thread.suspend、Thread.resume、Runtime.runFinalizersOnExit这些终止线程运行的方法已经被废弃了,使用它们是极端不安全的。

正确停止线程的方法:

​ 第一:正常执行完run方法,然后结束掉。

​ 第二:控制循环条件和判断条件的标识符来结束掉线程。

2)实现代码示例

class MyThread extends Thread { int i=0; boolean next=true; @Override public void run() { while (next) { if(i==10) next=false; i++; System.out.println(i); } } }

4.7、线程打断---interrupt

1)什么是中断(interrupt)

​ 中断只是一种协作机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现;

​ 每个线程对象中都有一个标识,用于表示线程是否被中断;该标识位为true表示中断,为false表示未中断;

​ 通过调用线程对象的interrupt方法将该线程的标识位设为true;可以在别的线程中调用,也可以在自己的线程中调用。

打断标记:线程是否被打断,true表示被打断了,false表示没有

2)涉及方法

isInterrupted()方法:

获取线程的打断标记(哪个线程对象调用就检查谁的) ,调用后不会修改线程的打断标记

interrupt()方法:

中断this线程(哪个线程对象调用即中断谁)。如果这个需要被中断线程处于阻塞状态(sleep、wait、join),那么它的中断状态就会被清除,并且抛出异常(InterruptedException)。这个中断并非真正的停止掉线程,而是将它的中断状态设置成"停止"的状态,线程还是会继续运行,至于怎么停止掉该线程,还是要靠我们自己去停止,该方法只是将线程的状态设置成"停止"的状态,即true。

打断正常线程 ,线程不会真正被中断,但是线程的打断标记为true。

interrupted()方法:

检查当前线程是否被中断,与上面的interrupt()方法配合一起用。线程的中断状态将会被这个方法清除,也就是说:如果这个方法被连续成功调用两次,第二次

调用将会返回false(除非当前线程在第一次调用之后和第二次调用之前又被中断了)。

也就是说:调用后清空打断标记 即如果获取为true 调用后打断标记为false (不常用)

4.8、线程堵塞

线程的阻塞可以分为好多种,从操作系统层面和java层面阻塞的定义可能不同,但是广义上使得线程阻塞的方式有下面几种:

1)BIO阻塞,即使用了阻塞式的io流

2)sleep(long time) 让线程休眠进入阻塞状态

3)a.join() 调用该方法的线程进入阻塞,等待a线程执行完恢复运行

4)sychronized或ReentrantLock 造成线程未获得锁进入阻塞状态

5)获得锁之后调用wait()方法 也会让线程进入阻塞状态

6)LockSupport.park() 让线程进入阻塞状态

 

本文首发于java黑洞网,博客园同步更新












原文转载:http://www.shaoqun.com/a/623649.html

跨境电商:https://www.ikjzd.com/

易佰:https://www.ikjzd.com/w/1482

terapeak:https://www.ikjzd.com/w/556


前言线程池,故名思意,就是一个存放线程的池子,学术一点的说法,就是一组存放线程资源的集合。为什么有线程池这一概念地产生呢?想想以前我们都是需要线程的时候,直接自己手动来创建一个,然后执行完任务我们就不管了,线程就是我们执行异步任务的一个工具或者说载体,我们并没有太多关注于这个线程自身生命周期对于系统或环境的影响,而只把重心放在了多线程任务执行完成的结果输出,然后目的达到了,但是真正忽略了线程资源的
tinypic:https://www.ikjzd.com/w/114
isbn:https://www.ikjzd.com/w/174
刘军:https://www.ikjzd.com/w/1835
跨境电商品牌走向世界 从海外华人消费看电商选品:https://www.ikjzd.com/home/135612
7.2亿次浏览量,TikTok网红带火的亚马逊品牌,销量翻倍:https://www.ikjzd.com/home/123363
分享一个淘宝京东图片下载插件:https://www.ikjzd.com/tl/109337

从sql语句的角度解刨SqlServer插入语句的并发问题

今天收到一个小学弟的求助,数据库插入偶尔重复,怎么在sql语句上进行解决。


 

Q:学长,我导入excel数据的操作,平时使用好好的,怎么突然发生插入重复的问题?

A:你是使用哪个ORM框架进行操作的?

 

Q:什么是ORM框架?

A:额……,你数据库怎么链接操作的?

 

Q:我使用Connection对象进行链接操作的。

A:哦,ADO.NET呀,你把导入数据的插入sql语句的截图发出来看看。

 

Q:sql截图(这里就不展示了,就是一个简单的insert into,如:INSERT INTO aTable(id) VALUES("1"))

A:哦哦,你语句没有并发情况下没问题,但是多人同时导入数据就存在并发,数据重复意料之中。

 

Q:啊,这还涉及到并发?那我怎么修改呀

A:简单,不改变其他操作的情况下,你把插入语句加事务加锁机制既可以了。

 

Q:额……不怎么懂,有demo吗?

A:没事,我就在你的sql语句上优化下,你直接粘贴就可以了。

 


 

我们来解刨一下这个问题,现在很多人依赖ORM,都没怎么写sql了,我们就从sql的角度解析一下这个问题。

这里不好提供代码展示,我们这里就简单进行一个模拟还原使用场景。

创建一个表,命名为aTable,里面就一个字段id,int类型,然后插入一个数据为1;

 

操作一:重现问题出现原因

然后同时(有点间隔也没关系,但隔时间要小)在查询分析器的两个窗口中执行下如下语句:

declare @id intset @id = ( select max(id) from aTable )while @id < 40000 begin set @id = @id + 1 insert into aTable ( id ) select @id set @id = ( select max(id) from aTable ) end

这样的目的在于测试当两个用户同时操作同一个表时的重复性操作,模拟多用户同时导入相同的excel数据,

结果:共得到42953条数据,其中2953条重复,当然,这个重复数据跟执行间隔时间有关。


 

操作二:进行第一步优化,添加事务

 sql语句加上事务处理,

然后同时(有点间隔也没关系,但间隔时间要小)在查询分析器的两个窗口中执行下如下语句:

begin tran --开启事务declare @id intset @id = ( select max(id) from aTable )while @id < 40000 begin set @id = @id + 1 insert into aTable ( id ) select @id set @id = ( select max(id) from aTable ) endcommit tran --提交事务

结果:共得到40000条数据,无重复,但是执行时间是没加事务处理时的6倍,时间太久。


 

操作三:进行第二步优化,添加锁

 sql语句加上事务处理和锁机制,

然后同时(有点间隔也没关系,但间隔时间要小)在查询分析器的两个窗口中执行下如下语句:

begin tran --开始事务

declare @id INT
set @id = ( select max(id) from aTable )
while @id < 40000
begin
set @id = @id + 1
--添加锁 with(tablock)
insert into aTable with (tablock) ( id ) select @id
set @id = ( select max(id) from aTable )
end

commit tran --提交事务


结果:共得到40000条数据,无重复,执行时间快。


 

这样就从sql上简单解决并发问题啦,当然,还有其他问题和解决方法,

这里就不做叙说了,具体情况遇到再分析,拜拜。

 


欢迎关注订阅我的微信公众平台【熊泽有话说】,更多好玩易学知识等你来取
作者:熊泽-学习中的苦与乐
公众号:熊泽有话说
出处:  https://www.cnblogs.com/xiongze520/p/14524707.html
创作不易,转载或者部分转载、摘录,请在文章明显位置注明作者和原文链接。  

 









原文转载:http://www.shaoqun.com/a/622662.html

跨境电商:https://www.ikjzd.com/

blibli:https://www.ikjzd.com/w/1676

败欧洲网站:https://www.ikjzd.com/w/1555


今天收到一个小学弟的求助,数据库插入偶尔重复,怎么在sql语句上进行解决。Q:学长,我导入excel数据的操作,平时使用好好的,怎么突然发生插入重复的问题?A:你是使用哪个ORM框架进行操作的?Q:什么是ORM框架?A:额……,你数据库怎么链接操作的?Q:我使用Connection对象进行链接操作的。A:哦,ADO.NET呀,你把导入数据的插入sql语句的截图发出来看看。Q:sql截图(这里就不展
grab:https://www.ikjzd.com/w/841
李群:https://www.ikjzd.com/w/1767
cima是什么:https://www.ikjzd.com/w/1372
亚马逊被恶意篡改?卖家别再为竞争对手引流带货了!:https://www.ikjzd.com/home/120727
口述:老公抱回私生子孩他妈成谜老公私生子离婚:http://lady.shaoqun.com/m/a/36495.html
美国将2000亿美元关税税率提高至25%?中方:已做好充分准备!:https://www.ikjzd.com/home/4004

4个小技巧带你玩转跨境电商邮件营销

电子邮件是一种公认的高效廉价的营销手段,研究表明,电子邮件的ROI为122%,是社交媒体和付费搜索等其他营销策略回报率的4倍以上。

我们可以这样说,电子邮件营销不仅有用,而且很有必要。

那跨境电商该如何进行邮件营销,提升店铺营销额呢?主要是以下四点:

1.访客分类,精细化运营

我们依据是否下单这个标准,把访客分为三类:潜在客户、初次购买者和忠实用户(复购)。针对登陆网站但并未下单的潜在用户,可以发送"产品热销"邮件或者弃购挽回邮件,促使完成订单;

针对初次购买者,可以根据购买的商品了解访客喜好,从而推荐相关产品,追加销售;

对于忠实用户,可以向他们了解产品反馈,以便更好地改进;同时还可以给予VIP特别优惠,增加复购。

2.简洁标题,提升点击率

标题内容要简短有力,同时包含以下内容:

表明发件人身份:标题可以和寄件者名称相呼应,表明公司或品牌,让收件人放心打开。

准确描述邮件内容:概括邮件主要内容,包括产品信息、优惠活动、活动截止时间等。

重要的关键词布局:邮件现在不被打开不代表以后也不打开,布局关键词利于用户进行邮件搜索。

3.文档预处理,确保附件打开

世界之大,无奇不有。你要知道,不是全球所有的电脑、手机都预装了office、WPS等办公软件的。提前对文件进行处理,编写电子邮件时,上传office、pdf、jpg多个格式的附件,确保意向客户在手机端或者电脑端都能查看。

4.选择合适的时间发送邮件

发送邮件,选定最佳时间邮件营销不仅要与黑五网一这样的大促相结合,它也是日常维系客户的重要手段。及时告知那些忠粉,店铺的促销信息、上架新品等动态。

研究表明,一号是一个月中最适合发送邮件的日子,平均打开率约为16.4%,紧随其后的是4号、11号和19号,也是卖家发送邮件的优选。具体到一天中,8:00和13:00是平均打开率和点击率最高的时间段,也就是发送邮件的最佳时间点。

好了,以上就是本次分享的内容,希望能对你有所帮助!

文章来源:https://www.ikjzd.com/home/143094

跨境电商:https://www.ikjzd.com/

net a porter:https://www.ikjzd.com/w/2132

粉丝通:https://www.ikjzd.com/w/743

东杰智能:https://www.ikjzd.com/w/1967

4个小技巧带你玩转跨境电商邮件营销

电子邮件是一种公认的高效廉价的营销手段,研究表明,电子邮件的ROI为122%,是社交媒体和付费搜索等其他营销策略回报率的4倍以上。我们可以这样说,电子邮件营销不仅有用,而且很有必要。那跨境电商该如何进行邮件营销,提升店铺营销额呢?主要是以下四点:1.访客分类,精细化运营我们依据是否下单这个标准,把访客分为三类:潜在客户、初次购买者和忠实用户(复购)。针对登陆网站但并未下单的潜在用户,可以发送"产品

欧联-拉梅拉中柱凯恩梅开二度 热刺2-0完胜劲旅_皮球

原标题:欧联-拉梅拉中柱凯恩梅开二度 热刺2-0完胜劲旅

北京时间3月12日凌晨4时整,2020-2021赛季欧联杯八分之一决赛首回合的一场焦点战在托特纳姆热刺球场展开角逐,由热刺坐阵主场迎战克罗地亚足球甲级联赛劲旅萨格勒布迪纳摩。上半场,拉梅拉连续突破后搓射击中立柱,哈里-凯恩补射空门得分。下半场,哈里-凯恩利用对手的失误扩大比分。最终,热刺主场2-0战胜萨格拉布迪纳摩。

比赛刚开场,奥尔西奇禁区左侧左脚低射,皮球被洛里收入怀中。第21分钟,伊万努舍茨得球后内切劲射,皮球高出横梁。第24分钟,热刺打破场上僵局,拉梅拉前场得球后连续突破至点球点处,随后完成左脚外脚背射门,皮球击中右侧立柱后弹出,哈里-凯恩门前补射空门得分,1-0!

第30分钟,佩特科维奇弧顶前得球后内切远射,皮球被洛里鱼跃扑出。第33分钟,戴尔鼻子出血,在场边进行简单的治疗之后再次回到赛场。

下半场双方易边再战。第46分钟,孙兴慜禁区左侧回传,本-戴维斯左路左脚传中,拉梅拉禁区内一人倚住防守球员后制造了混乱,但裁判示意拉梅拉越位在先。第48分钟,恩东贝莱禁区右侧踩单车突破时被马耶尔踢倒在地,裁判没有理会,这引起了穆里尼奥和球员们的不满。第53分钟,孙兴慜反击中左路传中,哈里-凯恩后点头球摆渡,防守球员赶在阿里射门前将皮球破坏。第58分钟,萨格拉布迪纳摩错过破门良机,奥尔西奇前场右路反击中送出精准低平球传中,佩特科维奇后点左脚推射,皮球偏出门框范围。第64分钟,替补登场的贝尔前场右路送出精妙左脚外脚背传球,贝尔温后点右脚凌空推射,皮球被利瓦科维奇扑出。

第69分钟,热刺扩大了领先优势,恩东贝莱大范围转移,奥里耶右路低平球传中,泰奥菲勒-卡特林门前解围时失误,哈里-凯恩得球后冷静的扣球过人,随后低射破门,2-0!

第76分钟,萨格勒布迪纳摩开出右侧角球,拉斯穆斯-劳里森门前高高跃起头球攻门,哈里-凯恩门前将皮球破坏。第81分钟,哈里-凯恩为热刺赢得前场位置极佳的定位球,贝尔主罚并选择左脚直接射门,皮球绕过人墙后飞入球门左侧死角,利瓦科维奇迅速移动将皮球单掌扑出。第85分钟,赫伊别尔中场战术犯规吃到黄牌,他将因累积黄牌错过双方下回合较量。补时阶段,贝尔温前场左侧传中,贝尔后点小角度垫射偏出底线。

最终,热刺主场2-0战胜萨格拉布迪纳摩。

双方出场阵容:

热刺(4-2-3-1):1-洛里/33-本-戴维斯、6-达文森-桑切斯、15-戴尔、24-奥里耶/20-阿里(27-小卢卡斯 64')、28-恩东贝莱(5-赫伊别尔 71')/17-穆萨-西索科、11-拉梅拉(9-贝尔 64')、7-孙兴慜(23-贝尔温 64')/10-哈里-凯恩(45-卡洛斯-维尼修斯 83')

萨格勒布迪纳摩(4-1-4-1):40-利瓦科维奇/22-莱奥瓦茨、28-泰奥菲勒-卡特林、6-拉斯穆斯-劳里森、13-里斯托夫斯基/5-阿代米(38-弗兰季奇89')/17-伊万努舍茨、97-亚基奇、10-马耶尔(20-卡斯特拉蒂 64')、99-奥尔西奇(80-阿蒂姆温 64')/21-佩特科维奇(11-加夫拉诺维奇 77')

双方技术统计:

返回搜狐,查看更多

责任编辑:

原文转载:http://sport.shaoqun.com/a/482740.html

跨境电商:https://www.ikjzd.com/

netporter:https://www.ikjzd.com/w/2132

洋老板:https://www.ikjzd.com/w/2779


原标题:欧联-拉梅拉中柱凯恩梅开二度热刺2-0完胜劲旅北京时间3月12日凌晨4时整,2020-2021赛季欧联杯八分之一决赛首回合的一场焦点战在托特纳姆热刺球场展开角逐,由热刺坐阵主场迎战克罗地亚足球甲级联赛劲旅萨格勒布迪纳摩。上半场,拉梅拉连续突破后搓射击中立柱,哈里-凯恩补射空门得分。下半场,哈里-凯恩利用对手的失误扩大比分。最终,热刺主场2-0战胜萨格拉布迪纳摩。比赛刚开场,奥尔西奇禁区左侧
抢注商标:https://www.ikjzd.com/w/1053
modcloth:https://www.ikjzd.com/w/1271
海维:https://www.ikjzd.com/w/1891
十种最常见又黑心的亚马逊恶意竞争手段 :https://www.ikjzd.com/home/5297
返校季什么好卖?这份返校季营销全攻略收好了!:https://www.ikjzd.com/home/104321
2019亚马逊Q1季最新政策调整复盘,你错过了哪些?:https://www.ikjzd.com/home/20062

抗癌突破!国内成功实施先进疗法,生存期再延长,哪些患者能做?

核心提示:2月18日,《癌症免疫治疗杂志》期刊发表了一则中国采取CAR-T疗法治疗晚期难治性卵巢癌的案例。

你知道吗,世界范围内,每年因癌而死的人高达996万,新发癌症人数达1929万。(数据来源:世界卫生组织2020年全球癌症负担

这么多人,都希望自己的癌症能够治愈,但很可惜,作为现今最大的医学难题,癌症仍然让医学人员感到很"头疼"。

而一种新型疗法的出现,似乎带来了一束曙光。

一、最新报告:新型CAR-T疗法效果显著!

CAR-T,英文的全称是Chimeric Antigen Receptor T-Cell Immunotherapy,翻译成中文是"嵌合抗原受体T细胞免疫疗法",该疗法是今年来癌症治疗领域研究的重点。

2月18日,《癌症免疫治疗杂志》期刊发表了一则中国采取CAR-T疗法治疗晚期难治性卵巢癌的案例。

这是一名54岁的晚期卵巢浆液性腺癌患者,患者在接受该疗法前,使用紫杉醇联合顺铂化疗了8次,之后又用吉西他滨联合奥沙利铂的治疗方案,随后出现了转移性肝部病变,在采取阿帕替尼治疗后,病情趋于稳定。

但在这之后,患者再次出现复发。由于属于晚期难治性卵巢癌,在通过各项检查后,她被纳入了新疗法临床试验的试验组。

2018年12月,患者第一次接受了CAR-T细胞治疗,并且在2019年的1月接受了第二次治疗。在使用该疗法之后,患者的N2转移病灶缩小到无法检测无进展生存期达到了5个月,生存期达到了17个月。

二、"神奇"的CAR-T疗法,能治疗哪些癌症?

CAR-T疗法,就是将抗体的轻重链连接到T细胞表面TCR的恒定区上,产生肿瘤特异性识别的T细胞,然后输回患者体内,展开对癌细胞的杀灭。在相关的临床试验中,针对血液肿瘤疾病的效果较好。

1.非霍奇金淋巴瘤

该肿瘤疾病侵袭性强,而且在治疗阶段容易恶化,并且发生转移或者复发。在相关的临床试验中,使用CAR-T细胞治疗方案,80%的参与者在半年之内没有发生复发。而在另外的一项临床试验中,82%的患者病情进展减缓,54%的患者病情消失,持续9个月后仍然有40%的患者没有出现复发。

2.儿童急性淋巴细胞白血病

使用CAR-T细胞疗法进行治疗后,75%的患者半年后没有复发,2017年,美国食品和药品管理局批准该疗法正式进入临床应用。

3.多发性骨髓瘤

该病是骨髓中浆细胞的血癌,其5年生存率只有50%。2017年ASCO年会上,使用CAR-T细胞疗法的临床试验表明,94%的患者在接受治疗后的两个月内,疾病出现了明显的缓解。

此外,针对肝癌、肺癌、乳腺癌、结直肠癌等实体肿瘤,国内也在积极开展临床研究和应用,并且取得了一定的成效。

不过,和其他的治疗方法一样,CAR-T细胞疗法也有自己的优缺点。

三、理性看待CAR-T疗法的优缺点

CAR-T疗法的针对性较强,而且在临床上对于不同的患者,可以采取相对个性化的治疗方案。但也正是因为其的个性化方式,从而在临床的具体应用中,施行起来的难度和成本就相对较高。

难点1:制作工艺要求高

CAR-T产品生产工艺要求很高,成本昂贵。因为是在体外人工改造患者的T细胞,从收集患者的免疫细胞,到体外改造,再到输回患者体内,整个过程非常复杂,不能出现一定点的差错,所以对GMP(良好生产规范)和工艺效率有着极高要求。

难点2:复发情况

和其他的治疗方式一样,CAR-T疗法虽然效果不错,但也存在复发的情况。据《Nature》杂志的报告,有数据显示,在相关的试验中,接受CD19的CAR-T疗法的某些类型患者,12个月内出现复发的几率高达50%,通常是抗原阳性的肿瘤细胞早期复发,和抗原丢失的肿瘤细胞晚期复发。而一旦出现复发,接下来的治疗就成为了新难点。

难点3:价格高

该治疗方法类似于"私人订制",质检成本、运营成本、生产工艺成本等一系列因素综合在一起,导致其最终的价格非常的高昂。目前,美国的两款CAR-T产品,定价是47.5万美元和37.3万美元。由于价格昂贵,所以市场潜力受到了限制。

而在国内,首款CAR-T疗法"益基利仑赛注射"已进入审批阶段,不过市场定价还没确定。相关人士表示,国内价格定在30万-50万之间,是一个相对可以接受的定位,如果跟美国价格类似,大众将难以接受,也就失去了临床优势。

但目前来看,其价格走势仍然未知。

总体而言,CAR-T疗法由于其高定制性和生产过程的不确定因素,导致价格相对较高。对绝大多数患者而言,可能更会考虑性价比更高的治疗方案。


参考资料:

[1]专访许晓椿博士:CAR-T疗法领跑,生产工艺为先,自动化制造是关键.生物谷,2019.4.8


[2]生存达17个月!12年剑指实体瘤!新型CAR-T联合疗法治疗卵巢癌带来惊喜.环宇达康,2020.2.22

[3]首款上市在即,国内CAR-T疗法如何定价?.求实药社,2021.1.19

未经作者允许授权,禁止转载


原文转载:http://health.shaoqun.com/a/201112.html

跨境电商:https://www.ikjzd.com/

贝恩投资公司:https://www.ikjzd.com/w/1336

tiki:https://www.ikjzd.com/w/2053


核心提示:2月18日,《癌症免疫治疗杂志》期刊发表了一则中国采取CAR-T疗法治疗晚期难治性卵巢癌的案例。 你知道吗,世界范围内,每年因癌而死的人高达996万,新发癌症人数达1929万。(数据来源:世界卫生组织2020年全球癌症负担)这么多人,都希望自己的癌症能够治愈,但很可惜,作为现今最大的医学难题,癌症仍然让医学人员感到很"头疼"。而一种新型疗法的出现,似乎带来了一束曙光。一、最新报告:新型C
prezi:https://www.ikjzd.com/w/1751
贝恩资本:https://www.ikjzd.com/w/1336
海拍客:https://www.ikjzd.com/w/1742
正在崛起的亚马逊加拿大站,30天销量猛增3倍!:https://www.ikjzd.com/home/124576
做亚马逊从入门到放弃,我收获了这些……:https://www.ikjzd.com/home/105269
实操干货:怎样设置带有中划线效果的商品促销价格?:https://www.ikjzd.com/home/107285

订单最长延期9个月,美国家具市场严重缺货

2020年居家办公潮流的兴起促使家居行业大火,美国人对家居产品的需求也越来越强烈。而在2021年,伴随着美国房屋交付数量创下新高,这一火爆程度将持续下去。

 

家具订单最长延期9个月

 

据外媒报道,美国全境的家具零售商,都出现了长达数月的延迟交付问题,其订单普遍的延期在5-9个月。有美国消费者表示订购的沙发已经延迟了两周交付,但是根据客服的说法,沙发最早可能在4月1日到货,但请注意是最早,这也表示可能会出现遥遥无期的交付状况。

 

图1.jpg

 

而这种延迟交付只是美国家具市场的一个缩影,有美国商场的家居品牌表示,通常情况下,从中国进口家具只需要三个月的时间,但现在需要9个月的时间。

 

事实上,美国的家具多是从中国进口,但是目前中国的现状是原材料价格上涨,一些高价值的家具商品价格遭受波及。再加上,美国进口集装箱猛增217%,而出口的集装箱却是堆在港口,促使港口的运力难上加难,货运积压依旧存在,美国最大的洛杉矶港口已经濒临瘫痪状态。还有高居不下的运费状况依旧备受关注。

 

公司季度损失额高达3000万美元

 

数据显示,仅2021年2月份,美国人在家居和家装领域的花费就达到了113亿美元,同比增长了12%。事实上,美国市场对于家居等产品的需求很高,但是美国的制造能力普遍不高,这也就促使其家具等产品主要依赖进口。

 

图2.jpg

 

有美国家具公司表示,由于其产能不足以及后期供应链出现问题,导致商品交付延迟等状况层出不穷,公司的季度损失额高达3000万美元。不得不说,这一波损失也是让一众卖家肉疼。

 

中国卖家可抓住美国家具市场的商机,但是也要注意很多家具产品容易促使各种危险问题进而导致产品被召回或者下架。卖家需要把产品质量、安全问题放在首位,才有利于迎来再次爆单。





原文转载:http://www.shaoqun.com/a/621666.html

跨境电商:https://www.ikjzd.com/

ifttt:https://www.ikjzd.com/w/956

easybuy:https://www.ikjzd.com/w/2162


2020年居家办公潮流的兴起促使家居行业大火,美国人对家居产品的需求也越来越强烈。而在2021年,伴随着美国房屋交付数量创下新高,这一火爆程度将持续下去。家具订单最长延期9个月据外媒报道,美国全境的家具零售商,都出现了长达数月的延迟交付问题,其订单普遍的延期在5-9个月。有美国消费者表示订购的沙发已经延迟了两周交付,但是根据客服的说法,沙发最早可能在4月1日到货,但请注意是最早,这也表示可能会出现
primc:https://www.ikjzd.com/w/129
转运中国:https://www.ikjzd.com/w/1549
拍怕网:https://www.ikjzd.com/w/2205
DHL、UPS发布紧急通知:暂停部分国家进出口服务:https://www.ikjzd.com/home/118885
亚马逊差评应对策略:有了这几招,差评可以有效解决!:https://www.ikjzd.com/home/107254
stylenanda官网:https://www.ikjzd.com/w/1675.html

小姐姐经济,你必须了解一下

女性作为物质文明和精神文明的创造者,也是推动社会发展和进步的重要力量。后疫情时代下,一切仿佛按下1.5倍速的艰难时期,她们却成为促进消费、推动经济的重要力量,她们的力量绝对不容忽视。

消费又双叒叕是负增长

虽然近几个月政府一直致力于提振消费,并通过降税、补贴,多种渠道发放消费券等方式促进消费,但社会消费品零售仍低于预期。

国家统计局最新数据显示:

7月份,社会消费品零售总额32203亿元,同比下降1.1%;

1-7月份,社会消费品零售总额204459亿元,同比下降9.9%。

 国际金融专家赵庆明分析表示:

在收入和就业预期仍旧悲观的情况下,居民对可选消费品的消费仍然十分谨慎,竞品之间包括汽车、手机、家电等可选消费品之间的竞争,明显存在挤出效应。

(敲黑板!!知识点扩散↓↓)

挤出效应是政府为了平衡财政预算赤字,采取发行政府债券的方式,向私人借贷资金市场筹措资金,从而使市场利率上升,私人投资和支出因而相应地下降。这就是公共支出造成的财政赤字对私人投资和支出的挤出效应。

(emmmm简单来说就是,政府支出增加所引起的私人消费或投资降低的效果。)

小姐姐经济不可小觑

瑞银投资研究部发布中国股市上市公司二季度业绩的展望报告,其中在消费方面指出"小姐姐经济"将是新消费主题。


对于疫情后的消费情况,尽管疫情过后的总体消费复苏不及预期,但20—40岁年龄段高学历城市女性近期崛起成为了一个新的消费主题。

总体而言,这种"小姐姐经济"对化妆品、免税商品(包括化妆品和奢侈品)、医疗美容、手游和互联网内容影响重大。

更为重要的是,"小姐姐经济"可能会扩展到电商领域的家庭和儿童消费的方方面面,包括电商、娱乐、教育、孕产保健以及育儿产品和服务等。

如今在消费行业中一直流传着这样一句话"得女性者得天下","她经济"也是教育部2007年8月公布的171个汉语新词之一。自"她经济"的概念被提出以来,女性群体的力量价值日益凸显,逐渐成为新消费时代的主导力量。大数据显示,2020年中国"她经济"市场规模预计达到4.8万亿元。

据Mob研究院报告显示,目前女性消费主要集中在三个年龄段:中年女性、职场轻熟女性和校园女性。其中占比较大的还是为85后女性。

  • 75后女性的基础画像:已婚有娃,资深职场人士,关注投资理财,对于消费重心,倾向于家居,美容,家政服务,运动健康。

  • 85后女性的基础画像:已婚,职场展露头角,经济开始独立,对于美妆护肤,服饰家居,母婴,运动健康这几个方面是关注点最多的。

  • 95后女性的基础画像:未婚,收入来源于父母初为实习新人,职场新知女性,对于互联网应用,更了解。消费的重心为美妆,服饰,医美追星以及手游这几个方面为主。

乘风破浪的破产三姐妹

除了上文中提到的"小姐姐经济"影响颇深的美妆、手游、医美产业以外,还有三个新兴产业上涨势头可怕——汉服、Lolita服装、JK制服。

二次元及其衍生文化在90后女性群体之间的飞速兴起,逐渐从世人眼中的奇装异服,向新兴文化圈靠拢。随着大众审美多元化,汉服、Lolita、JK制服等泛二次元服装开始盛行,这类服装由于卖的贵、溢价高、消耗快被人们戏称为"破产三姐妹",正让小姐姐们"倾家荡产",她们却在每次还完"花呗",笑着说道"下个月又得吃土了"。

阿里巴巴公布数据显示,过去一年"破产三姐妹"的成交人数成倍增长,其中汉服成交人数同比增加149%,JK制服则增长351%。

数据来自Mob研究院


不仅如此,资本市场对于这些小姐姐消费的领域也开始追逐。

前段时间,主营汉服、JK制服等泛二次元相关产品的"十二光年"完成500万元天使轮融资;汉服品牌"十三余"宣布完成数千万Pre-A轮融资;汉服品牌"重回汉唐"获个人投资者及瑞羽行嘉等多家机构投资。

由此可见,不论是创业者,还是投资机构,都对这个由小姐姐消费撑起来的赛道青睐不已。

从消费者画像来看,破产三姐妹背后的消费者群体,就是年轻的小姐姐,其中20-29岁之间比例接近半数,其次为19岁以下。别看这群消费者年轻,可是消费能力不可小视,撑起来这百亿级别的赛道。 

数据来自Mob研究院


30+姐姐们的消费需求,了解一下

上文说到了小姐姐们,其中占据主导消费力量的85后姐姐,也就是30+姐姐们的消费市场又是什么样的呢?

首先"姐姐们"是谁?简言之,她们是追求精致生活和自我愉悦的新女性群体。根据 2019 年人口统计显示,中国30-55岁女性群体已经达到 2.78 亿,约占女性总人口的40.6%。在家庭里她们大多掌握财政大权,同时在消费市场中占有重要地位。

过去品牌以年轻女性和妈妈群体为主要目标,并未对姐姐群体单独细分,这一潜力巨大的市场有待进一步挖掘。同时,姐姐群体范围广大,收入水平、兴趣爱好和性能诉求各不相同,企业需要根据不同群体的需求精细化运营,才能投其所好,打开市场。

30+女性是高知高消的中坚力量。研究显示,这一群体中有 39% 拥有本科及硕士以上学历,高消倾向也显著高于整体人群。

精神层面,30+女性自我意识觉醒,追求健康舒适的品质生活,期望增加体验层次和丰富性。物质层面,高线城市精致女性收入高消费力强,低线新兴市场精致女性的消费欲和消费力也正迎头赶上。

在消费观上,姐姐们与其他年龄段女性不尽相同,她们更加注重提升生活的品质,希望增加生活的体验和丰富性。上一代女性以家庭和奉献为导向的消费观为主,更多为家庭而不是自身思考。

由于经济条件的大幅改善和独立意识的进一步觉醒,30+ 姐姐则更加兼顾家庭和自我需要是"爱家庭,也爱自我"的践行者。

与20+女性相比,姐姐们越发了解自我需求,对自己的宠爱越发实在逐渐呈现从向外展示(外秀)到向内感知(自我愉悦)的转变。除了注重服装、美容等外在形象外,也注重生活方方面面的品质感,例如饮食更健康,居住环境更舒适、偷悦等等。

因此,作为品牌方,我们需要:

1. 精细化投放,瞄准高价值的30+精致女性人群,深度发展核心群体

2. 拓展品牌传播范围,从公域到私域,实现引流到收割的品牌全链路营销。

3. 以品牌、产品为导向的内容,融合IP影响力,实现精准拓客

4. 人群多元化:不同30+女性圈层触达,通过数字化优势拓展更多的消费机会。


来源:全球红人营销


文章来源:https://www.ikjzd.com/home/143090

跨境电商:https://www.ikjzd.com/

败欧洲运费:https://www.ikjzd.com/w/1555

bonanza:https://www.ikjzd.com/w/275.html

marks spencer:https://www.ikjzd.com/w/2385

小姐姐经济,你必须了解一下

女性作为物质文明和精神文明的创造者,也是推动社会发展和进步的重要力量。后疫情时代下,一切仿佛按下1.5倍速的艰难时期,她们却成为促进消费、推动经济的重要力量,她们的力量绝对不容忽视。

欧盟进口管理制度ICS2即将生效,卖家注意了

DHL警告称,由于英国脱欧导致运输问题,ICS2将于周一生效。

事实证明,并非每个人都为脱欧做好了准备,因为脱欧后的运输仍存在一些问题,现在,从下周一开始,ICS2也是卖家需要担心的问题。

DHL提醒客户,欧盟距2021年3月15日推出ICS2的时间现在只有一周的时间。DHL表示,您必须提供运货单和商业/形式发票上准确和完整的数据,并且这些数据以电子方式提供给DHL。

这是一件头疼的事情,至关重要的是,为了您的包裹不会再次被延迟或退欧,必须确保发货人得到欧盟要求的信息,因此需要立即与您的发货人联系,以确保一切就绪。

DHL支持文件

欧洲(EU)海关进口指南提供了详细信息,以帮助您完成商业/形式发票。这包括有关在发票和运单上提供可接受的商品说明指南。

必须确保你的发货人得到欧盟要求的信息进口要求的详细信息,这些要求有助于确保在特定国家/地区顺利通关。

请注意,自2021年5月1日起,德国对B2B发货必须包括接收者的EORI号码。

Q:欧盟新的海关要求ICS2是什么?

ICS2(进口管制制度2)是新的欧盟安全申报管理制度,适用于输往欧盟关税地区(包括最终目的地或过境欧盟、挪威或瑞士)的货物。从2021年3月15日起,某些数据元素将被要求在出口国家通过飞往或过境欧盟、挪威或瑞士的航班装载之前发送给欧盟海关当局。

Q:您需要做什么才能为ICS2做好准备?

确保运单和商业/形式发票上包括完整和准确的发货人和收货人详细信息(包括收货人的全名)以及详细而准确的商品说明。此数据需要通过电子方式提交给DHL。

在可能的情况下,您的商业/形式发票上也应提供详细的项目数据,并以电子邮件提交。这将有助于确保在要求提供额外信息时,货物不会被欧盟海关标记/延迟。

Q:ICS2如何工作?

货物将在离开英国之前以电子方式提交给欧盟海关。关键数据,称为"预装货物信息"(PLACI(7 + 1)),包含以下字段:

*发货人姓名(货物的原始发送人)

*发货人地址

*收件人姓名

*收件人地址

*商品简介

*件数

*重量

*运单

如果正确提供了所有相关信息,欧盟海关将自动批准该批货物前往欧盟。ICS2的目的是进行安全检查,而不是提交海关申报单,因此,如果无法获得所需的正确无误数据,货物可能需要在英国停留,直到所要求的数据提供为止。因此,在最初创建装运文件时正确提供数据是至关重要的。



来源:美鸥网 Lib.


文章来源:https://www.ikjzd.com/home/143085

跨境电商:https://www.ikjzd.com/

crowd:https://www.ikjzd.com/w/880

打折网站:https://www.ikjzd.com/w/74

邮乐网购:https://www.ikjzd.com/w/1776

欧盟进口管理制度ICS2即将生效,卖家注意了

DHL警告称,由于英国脱欧导致运输问题,ICS2将于周一生效。 事实证明,并非每个人都为脱欧做好了准备,因为脱欧后的运输仍存在一些问题,现在,从下周一开始,ICS2也是卖家需要担心的问题。

亚马逊又出新政!看看更新了些啥?

铁子们晚上好!最近亚马逊更新了好多东西,小捷捷都有点看不过来了,特别是昨天更新的退货新政,引起了所有卖家的注意。

图片

相信很多卖家都遇碰到各种千奇百怪的退货理由:不合适,退!不喜欢,退!这些都还好,卖家最怕遇到那些不能退也要制造"机会"退和钻政策漏洞薅你羊毛的人,遇到这种人,卖家都要哭了呀!

特别是现在亚马逊更新的这条退货政策,一定会让骗子变本加厉地欺骗卖家。
我们先来看看新政的内容↓

"从2021年4月15日开始,我们将为您的客户提供无损且免费的替换品,作为符合条件的商品的一种选择,这是我们的"预付返还标签计划"的一部分。此项更改将为您提供其他退货解决方案,并使客户可以选择免费接收替换物品。 

除了可以要求对已损坏、有缺陷或与所订购产品不同的物品要求退款外,客户现在还可以选择更换产品。这样可以保留您的销售,而不会将交易转化为退款,客户将继续收到其商品的预付退货标签,无论他们要求更换还是退款。 

根据免费更换计划,客户有7天的时间来退回原始产品。扫描预付退货标签后,我们将收到客户退货的确认,并通知您寄出替换件,对于符合退回退款资格的商品,客户可以选择退回更换。" 

图片

这个通知一出,有卖家提出以下质疑:

1.这个货卖家没收到就要寄替换商品过去,卖家根本不知道会收到什么样的货物。如果遇到骗子,这将是一笔很大的损失。

2.谁来承担客户寄回来却无法作为新品出售货物的成本。

3.卖家会提供免费更换,但我们并不总是有库存。保证采购商的库存我们没有更多的问题。

.....

漏洞过于多,一时不知道该从哪里吐槽,反正卖家的利益就不是利益呗。如果有卖家真的遇到恶意退货的,一定要向平台申诉,维护自己的正当利益。

图片

被退回的的货物一般来说会有一些小瑕疵,处理这些货物的方式一般为一下几种: 

1、与热销产品捆绑销售,进行优惠处理; 

2、重新销售,但是价格要偏低,做成特价商品 ; 

3、可与公益组织合作,将东西捐赠给一些有需要的人。

对于这个退货新政,大家都有哪些看法呢?欢迎在评论区留言。





-END-




文章来源:https://www.ikjzd.com/home/143056

跨境电商:https://www.ikjzd.com/

一淘网比价平台:https://www.ikjzd.com/w/1698

reverb:https://www.ikjzd.com/w/1273

汇通达:https://www.ikjzd.com/w/1758

亚马逊又出新政!看看更新了些啥?

铁子们晚上好!最近亚马逊更新了好多东西,小捷捷都有点看不过来了,特别是昨天更新的退货新政,引起了所有卖家的注意。相信很多卖家都遇碰到各种千奇百怪的退货理由:不合适,退!不喜欢,退!这些都还好,卖家最怕遇到那些不能退也要制造"机会"退和钻政策漏洞薅你羊毛的人,遇到这种人,卖家都要哭了呀!特别是现在亚马逊更新的这条退货政策,一定会让骗子变本加厉地欺骗卖家。我们先来看看新政的内容↓"从2021年4月15

退役? 李根:本赛季是孙悦的最后一个CBA赛季_北京男篮

原标题:退役? 李根:本赛季是孙悦的最后一个CBA赛季

北京时间3月11日消息,在接受采访时,李根透露称本赛季是孙悦的最后一个CBA赛季。

"也有也没有吧,毕竟以前在一起的时候我们是队友,但现在,一个(孙悦)这也是最后一年了,另外一个(马布里)也是上了教练岗位两年了。在场下的感觉还在,不过在球场上训练,大家还是比较严肃的,生活当中还是以前的气氛。"当被问及还能否跟马布里和孙悦找回当年的感觉时,李根说道。

孙悦出生于1985年,曾在2007年在NBA选秀中被湖人队选走,并在2008年正式加盟湖人队,在随后的赛季也帮助湖人队夺得了NBA总冠军。

在2013年,孙悦加盟北京男篮,在之后也帮助北京男篮两次夺得CBA总冠军。并在2019年正式加盟北控男篮。本赛季孙悦共代表北控男篮出战19场比赛,场均可以得到4.2分、2.7个篮板、2.3次助攻以及1.9次封盖的全面数据。返回搜狐,查看更多

责任编辑:

原文转载:http://sport.shaoqun.com/a/481739.html

跨境电商:https://www.ikjzd.com/

review:https://www.ikjzd.com/w/2735

cicpa考试:https://www.ikjzd.com/w/1375


原标题:退役?李根:本赛季是孙悦的最后一个CBA赛季北京时间3月11日消息,在接受采访时,李根透露称本赛季是孙悦的最后一个CBA赛季。"也有也没有吧,毕竟以前在一起的时候我们是队友,但现在,一个(孙悦)这也是最后一年了,另外一个(马布里)也是上了教练岗位两年了。在场下的感觉还在,不过在球场上训练,大家还是比较严肃的,生活当中还是以前的气氛。"当被问及还能否跟马布里和孙悦找回当年的感觉时,李根说道。
stylenanda官网:https://www.ikjzd.com/w/1675.html
aicpa:https://www.ikjzd.com/w/1373
rfq:https://www.ikjzd.com/w/251
一款为全球卖家解决代发问题的工具ShopMaster:https://www.ikjzd.com/tl/107422
Wish年终旺季终极运营新思路分享 :https://www.ikjzd.com/home/11286
亚马逊卖家血与泪的教训,"质检"真的很重要!:https://www.ikjzd.com/home/20731

spring事务:事务控制方式,使用AOP控制事务,七种事务传播行为,声明事务,模板对象,模板对象原理分析

spring事务:事务控制方式,使用AOP控制事务,七种事务传播行为,声明事务,模板对象,模板对象原理分析

知识点梳理

课堂讲义

1)事务回顾

1.1)什么是事务-视频01

 

 

事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败。

1.2)事务的作用

事务特征(ACID)

  • 原子性(Atomicity)指事务是一个不可分割的整体,其中的操作要么全执行或全不执行

  • 一致性(Consistency)事务前后数据的完整性必须保持一致。比如:张三向李四转100元,转账前和转账后的数据是正确状态这叫一致性,如果出现张三转出100元,李四账户没有增加100元这就出现了数据错误,就没有达到一致性。

  • 隔离性(Isolation)事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离

  • 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

1.3)事务的隔离级别

隔离级别:isolation level

并发访问数据库时,在多个访问间进行相互隔离,防止并发访问操作的结果互相干扰。可能会出现的几种问题:

  • 脏读:允许读取未提交的信息Read uncommitted,解决方案:Read committed(表级读锁) 

 

 

  • 在这个场景中,B希望取款500元而后又撤销了动作,而A往相同的账户中转账100元,就因为A事务读取了B事务尚未提交的数据,因而造成账户白白丢失了500元

    xxxxxxxxxx 一个有结巴的人在饮料店柜台前转悠,老板很热情地迎上来说:"喝一瓶?"结巴连忙说:"我…喝…喝…"老板麻利地打开易拉罐递给结巴,结巴终于憋出了他的那句话:"我…喝…喝…喝不起啊!"
  • 不可重复读:A事务读取了B事务已经提交的更改数据

    解决方案: Repeatable read (行级写锁)MySQL InnoDB默认级别

    A在取款事务的过程中,B往该账户转账100元,A两次读取账户的余额发生不一致:

     

     

    在同一事务中,T4时间点和T7时间点读取账户存款余额不一样

  • 幻读:读取过程中数据条目发生了变化

    假设银行系统在同一个事务中,两次统计存款账户的总金额,在两次统计过程中,刚好新增了一个存款账户,并存入100元,这时,两次统计的总金额将不一致:

     

     

    解决方案: Serializable(表级写锁)

为了有效保证并发读取数据的正确性,用四种事务隔离级别来解决脏读、不可重复读、幻读等问题:

  • 未提交读(Read Uncommitted):允许脏读,可能读取到其他会话中未提交事务修改的数据(一般不用)

  • 提交读(Read Committed):只能读取到已经提交的数据,解决了脏读的问题

  • 可重复读(Repeatable Read):可重复读,MySQL InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻读

  • 串行读(Serializable):最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。虽然Serializable隔离级别下的事务具有最高的安全性,但是由于事务是串行执行,所以效率会大大下降,应用程序的性能会急剧降低。如果没有特别重要的情景,一般都不会使用Serializable隔离级别。

2)事务管理

回顾之前的事务管理方式

 

 

2.1)Spring事务核心对象-视频02

Spring提供如下三个接口为业务层提供了整套的事务解决方案

  • 事务定义对象:TransactionDefinition

  • 事务状态:TransactionStatus

  • 平台事务管理器:PlatformTransactionManager

2.2)TransactionDefinition

此接口定义了事务的基本信息

  • 获取事务定义名称

    String getName()
  • 获取事务的读写属性

    boolean isReadOnly()
  • 获取事务隔离级别

    int getIsolationLevel()
  • 获事务超时时间

    int getTimeout()
  • 获取事务传播行为特征

    int getPropagationBehavior()

2.3)TransactionStatus

此接口定义了事务在执行过程中某个时间点上的状态信息及对应的状态操作

 

 

2.4)PlatformTransactionManager

  • 平台事务管理器实现类

    • DataSourceTransactionManager 适用于Spring JDBC或MyBatis

    • HibernateTransactionManager 适用于Hibernate3.0及以上版本

    • JpaTransactionManager 适用于JPA

    • JdoTransactionManager 适用于JDO

    • JtaTransactionManager 适用于JTA

  • JPA(Java Persistence API)Java EE 标准之一,为POJO提供持久化标准规范,并规范了持久化开发的统一API,符合JPA规范的开发可以在不同的JPA框架下运行

  • JDO(Java Data Object )是Java对象持久化规范,用于存取某种数据库中的对象,并提供标准化API。与JDBC相比,JDBC仅针对关系数据库进行操作,JDO可以扩展到关系数据库、文件、

  • JTA(Java Transaction API)Java EE 标准之一,允许应用程序执行分布式事务处理。与JDBC相比,JDBC事务则被限定在一个单一的数据库连接,而一个JTA事务可以有多个参与者,比如JDBC连接、JDO 都可以参与到一个JTA事务中

此接口定义了事务的基本操作

  • 获取事务 :

    TransactionStatus getTransaction(TransactionDefinition definition)

     

  • 提交事务 :

    void commit(TransactionStatus status) 

     

  • 回滚事务 :

    void rollback(TransactionStatus status)

     

2.5)事务控制方式-视频03

  • 编程式

  • 声明式事务管理(

  • 声明式(注解)(重点)

2.6)制作案例

2.6.1)案例说明

银行转账操作中,涉及从A账户到B账户的资金转移操作;数据层仅提供单条数据的基础操作

2.6.2)案例环境准备

  • 数据层AccountDao提供对应的入账与出账操作

    /** * 入账操作 * @param name  入账用户名 * @param money  入账金额 */void inMoney(@Param("name") String name, @Param("money") Double money);/** * 出账操作 * @param name  出账用户名 * @param money  出账金额 */void outMoney(@Param("name") String name, @Param("money") Double money);

     

    AccountDao.

    <update id="inMoney"> update account set money = money + #{money} where name = #{name}</update><update id="outMoney"> update account set money = money - #{money} where name = #{name}</update>

     

  • 业务层接口AccountService提供转账操作

    /*** 转账操作* @param outName  出账用户名* @param inName  入账用户名* @param money  转账金额*/public void transfer(String outName,String inName,Double money);

     

  • 业务层实现提供转账操作:AccountServiceImpl

    public void transfer(String outName,String inName,Double money){  accountDao.outMoney(outName,money);  accountDao.inMoney(inName,money);}

     

2.6.3)编程式事务-视频04

  1. 在AccountServiceImpl中实现转账方法:

    private DataSource dataSource;public void setDataSource(DataSource dataSource) { this.dataSource = dataSource;}public void transfer(String outName, String inName, Double money) { //1.创建事务管理器,为事务管理器设置与数据层相同的数据源 PlatformTransactionManager ptm = new DataSourceTransactionManager(dataSource); //2.事务定义 TransactionDefinition td = new DefaultTransactionDefinition(); //3.创建事务状态对象,用于控制事务执行,开启事务 TransactionStatus ts = ptm.getTransaction(td);  accountDao.outMoney(outName,money); //模拟业务层事务过程中出现错误 int i = 1/0; accountDao.inMoney(inName,money);  //4.提交事务 ptm.commit(ts);}

     

  2. 在applicationContext.

    <??><beans ="http://www.springframework.org/schema/beans"  ="http://www.w3.org/2001/  ="http://www.springframework.org/schema/context"  ="http://www.springframework.org/schema/aop"  xsi:schemaLocation="http://www.springframework.org/schema/beans  https://www.springframework.org/schema/beans/spring-beans.xsd    https://www.springframework.org/schema/context/spring-context.xsd    https://www.springframework.org/schema/aop/spring-aop.xsd"> <context:property-placeholder location="classpath:*.properties"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">  <property name="driverClassName" value="${jdbc.driver}"/>  <property name="url" value="${jdbc.url}"/>  <property name="username" value="${jdbc.username}"/>  <property name="password" value="${jdbc.password}"/> </bean> <bean class="org.mybatis.spring.SqlSessionFactoryBean">  <property name="dataSource" ref="dataSource"/>  <property name="typeAliasesPackage" value="com.itheima.domain"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  <property name="basePackage" value="com.itheima.dao"/> </bean></beans>

     

  3. 将accountService需要的accountDao和dataSource注入进去

    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="dataSource" ref="dataSource"/></bean>

     

  4. 测试转账

    public class App { public static void main(String[] args) {  ApplicationContext ctx = new ClassPath);  AccountService accountService = (AccountService) ctx.getBean("accountService");  accountService.transfer("tom","itheima",100D); }}

     

 

2.7)使用AOP控制事务-视频05

1.将业务层的事务处理功能抽取出来制作成AOP通知,利用环绕通知运行期动态织入

public Object tx(ProceedingJoinPoint pjp) throws Throwable { DataSourceTransactionManager dstm = new DataSourceTransactionManager(); dstm.setDataSource(dataSource); TransactionDefinition td = new DefaultTransactionDefinition(); TransactionStatus ts = dstm.getTransaction(td);  Object ret = pjp.proceed(pjp.getArgs());  dstm.commit(ts); return ret;}

 

2.在applicationContext.

<bean id="txAdvice" class="com.itheima.aop.TxAdvice"> <property name="dataSource" ref="dataSource"/></bean>

 

3.配置事务管理AOP:使用环绕通知将通知类织入到原始业务对象执行过程中

<aop:config> <aop:pointcut id="pt" expression="execution(* com.itheima..transfer(..))"/> <aop:aspect ref="txAdvice">  <aop:around method="transactionManager" pointcut-ref="pt"/> </aop:aspect></aop:config>

 

4.测试转账

public class App { public static void main(String[] args) {  ApplicationContext ctx = new ClassPath);  AccountService accountService = (AccountService) ctx.getBean("accountService");  accountService.transfer("tom","itheima",100D); }}

 

 

2.8声明式事务(

使用声明式事务需要引入tx命名空间:

<??><beans ="http://www.springframework.org/schema/beans"  ="http://www.w3.org/2001/  ="http://www.springframework.org/schema/context"  ="http://www.springframework.org/schema/aop"  ="http://www.springframework.org/schema/tx"  xsi:schemaLocation="http://www.springframework.org/schema/beans  https://www.springframework.org/schema/beans/spring-beans.xsd    https://www.springframework.org/schema/context/spring-context.xsd    https://www.springframework.org/schema/tx/spring-tx.xsd    https://www.springframework.org/schema/aop/spring-aop.xsd">

 

2.8.1)tx:advice

  • 名称:tx:advice

  • 类型:标签

  • 归属:beans标签

  • 作用:配置事务专属通知类

  • 格式:

    <beans> <tx:advice id="txAdvice" transaction-manager="txManager"> </tx:advice></beans>

     

  • 基本属性:

    • id :用于配置aop时指定通知类的id

    • transaction-manager :指定事务管理器bean

2.8.2)tx:attributes

  • 名称:tx:attributes

  • 类型:标签

  • 归属:tx:advice标签

  • 作用:定义通知属性

  • 格式:

    <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes>  <tx:method name="*" read-only="false" />  <tx:method name="get*" read-only="true" />  <tx:method name="find*" read-only="true" />  </tx:attributes></tx:advice>

     

2.8.3)aop:advisor

使用aop:advisor在AOP配置中引用事务专属通知类

<aop:config> <aop:pointcut id="pt" expression="execution(* com.itheima.service.*Service.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/></aop:config>

 

 

2.8.4) 使用

  1. 设置事务管理器

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/></bean>

     

  2. 配置专用事务通知器

    <!--定义事务管理的通知类--><tx:advice id="txAdvice" transaction-manager="txManager"> <!--定义控制的事务--> <tx:attributes>  <tx:method name="*" read-only="false"/>  <tx:method name="get*" read-only="true"/>  <tx:method name="find*" read-only="true"/>  <tx:method name="transfer" read-only="false"/> </tx:attributes></tx:advice>

     

  3. AOP配置切面,使用通知器绑定切入点

    <aop:config> <aop:pointcut id="pt" expression="execution(* com.itheima.service.*Service.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/></aop:config>

     

  4. 测试转账

    public class App { public static void main(String[] args) {  ApplicationContext ctx = new ClassPath);  AccountService accountService = (AccountService) ctx.getBean("accountService");  accountService.transfer("tom","itheima",100D); }}

     

     

事务的应用层场景

J2EE开发使用分层设计的思想进行,对于简单的业务层转调数据层的单一操作,事务开启在业务层或者数据层并无太大差别;当业务中包含多个数据层的调用时,需要在业务层开启事务,对数据层中多个操作进行组合并归属于同一个事务进行处理。

2.8.5)tx:method-视频07

  • 名称:tx:method

  • 类型:标签

  • 归属:tx:attribute标签

  • 作用:设置具体的事务属性

  • 格式:

    <tx:attributes> <tx:method name="*" read-only="false" /> <tx:method name="get*" read-only="true" /></tx:attributes>

     

  • 说明:

    通常事务属性会配置多个,包含1个读写的全事务属性,1个只读的查询类事务属性

tx:method属性

 

 

2.9)事务传播行为-视频08

 

 

  • 事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播

    public void methond1() { //在事务中执行 methond2();  //doSomething}public void methond2() { //在事务中执行 //doSomething}

     

2.10)七种事务传播行为(了解)

Spring提供了七种事务传播行为,默认值为 REQUIRED

  • REQUIRED(需要): 如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务 

  

 

 

  • REQUIRES_NEW(需要新的): 新建事务,如果当前存在事务,把当前事务挂起 

  

 

 

  • SUPPORTS: 支持当前事务,如果当前没有事务,就以非事务方式执行 

 

  • NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起 

 

  • MANDATORY(强制的): 使用当前的事务,如果当前没有事务,就抛出异常 

 

  • NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常 

  • NESTED: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED类似的操作。

2.11)事务传播应用场景

生成订单业务需要3个步骤来完成:

  1. 子业务S1:记录日志到数据库表log

  2. 子业务S2:保存订单数据到数据库表order

  3. 子业务S3:更新支付表Z中的订单支付状态order_pay

 

 

如果S2或S3事务提交失败,S1需要保证本次数据库操作的日志记录,因此不能对S1的数据库操作进行回滚。

解决方案:S1需要在单独的事务中执行,传播行为配置为REQUIRES_NEW

2.12)声明式事务(注解)-视频09

2.12.1)@Transactional

  • 名称:@Transactional

  • 类型:方法注解,类注解,接口注解

  • 位置:方法定义上方,类定义上方,接口定义上方

  • 作用:设置当前类/接口中所有方法或具体方法开启事务,并指定相关事务属性

  • 范例:

    @Transactional( readOnly = false, timeout = -1, isolation = Isolation.DEFAULT, rollbackFor = {ArithmeticException.class, IOException.class}, noRollbackFor = {}, propagation = Propagation.REQUIRES_NEW)public void methond() {}

     

  • 注意事项

    • 只能应用到 public 方法上,如果在 protectedprivate或者默认可见性的方法上使用事务控制将被忽略,也不会抛出任何异常。

    • 如果类级别配置了注解,方法级别也配置了,应用程序会以方法上配置的事务属性信息来管理事务,换言之,方法级别的事务属性信息会覆盖类级别的相关配置。

2.12.2)tx:annotation-driven

  • 名称:tx:annotation-driven

  • 类型:标签

  • 归属:beans标签

  • 作用:开启事务注解驱动,并指定对应的事务管理器

  • 范例:

    <tx:annotation-driven transaction-manager="txManager"/>

     

2.12.3 使用注解完成转账事务控制

1.在applicationContext.

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  <property name="dataSource" ref="dataSource"/></bean><tx:annotation-driven transaction-manager="txManager"/>

 

2.在transfer方法上使用@Transactional注解进行事务控制

@Transactional(  readOnly = false,  timeout = -1,  isolation = Isolation.DEFAULT,  rollbackFor = {},  noRollbackFor = {},  propagation = Propagation.REQUIRED)public void transfer(String outName, String inName, Double money) { accountDao.outMoney(outName,money); int i = 1/0; accountDao.inMoney(inName,money);}

 

3.测试转账

public class App { public static void main(String[] args) {  ApplicationContext ctx = new ClassPath);  AccountService accountService = (AccountService) ctx.getBean("accountService");  accountService.transfer("tom","itheima",100D); }}

 

 

2.13)声明式事务(纯注解驱动)-视频10

  • 名称:@EnableTransactionManagement

  • 类型:类注解

  • 位置:Spring注解配置类上方

  • 作用:开启注解驱动,等同

  • 范例:

    public class TransactionManagerConfig { @Bean public PlatformTransactionManager getTransactionManager(@Autowired DataSource dataSource){  return new DataSourceTransactionManager(dataSource); }}

     

启用事务管理:在SpringConfig类上导入TransactionManagerConfig

 @Import({JDBCConfig.class,MyBatisConfig.class,TransactionManagerConfig.class}) @EnableTransactionManagement @Configuration @ComponentScan("com.itheima") @PropertySource("classpath:jdbc.properties") @Import({JDBCConfig.class,MyBatisConfig.class,TransactionManagerConfig.class}) @EnableTransactionManagement public class SpringConfig { }

 

 

3)模板对象(了解)

3.1)Spring模板对象-视频11

Spring提供如下的模板对象:

  • JdbcTemplate

  • RedisTemplate

  • RestTemplate

  • RabbitTemplate

  • TransactionTemplate

  • JmsTemplate

  • HibernateTemplate

  • ...

3.2)JdbcTemplate

3.2.1 JdbcTemplate简介

JdbcTemplate是Spring对JDBC的封装,提供标准的sql语句操作API,目的是使JDBC更加易于使用。

  1. update:用于执行INSERTUPDATEDELETE等语句。

    public void save(Account account) { String sql = "insert into account(name,money)values(?,?)"; jdbcTemplate.update(sql,account.getName(),account.getMoney());}

     

  2. queryXxx:用于执行SELECT数据查询语句。

    public String findNameById(Integer id) { String sql = "select name from account where id = ? "; //单字段查询可以使用专用的查询方法,必须制定查询出的数据类型,例如name为String类型 return jdbcTemplate.queryForObject(sql,String.class,id );}

     

3.2.1 使用JdbcTemplate

  1. 在JDBCConfig类中注册JdbcTemplate

    public class JDBCConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String userName; @Value("${jdbc.password}") private String password; @Bean("dataSource") public DataSource getDataSource(){  DruidDataSource ds = new DruidDataSource();  ds.setDriverClassName(driver);  ds.setUrl(url);  ds.setUsername(userName);  ds.setPassword(password);  return ds; } //注册JdbcTemplate模块对象bean @Bean("jdbcTemplate") public JdbcTemplate getJdbcTemplate(@Autowired DataSource dataSource){  return new JdbcTemplate(dataSource); } @Bean("jdbcTemplate2") public NamedParameterJdbcTemplate getJdbcTemplate2(@Autowired DataSource dataSource){  return new NamedParameterJdbcTemplate(dataSource); }}

     

  2. 使用JdbcTemplate实现AccountDaoImpl中的所有方法

    //dao注册为bean@Repository("accountDao")public class AccountDaoImpl implements AccountDao { //注入模板对象 @Autowired private JdbcTemplate jdbcTemplate; public void save(Account account) {  String sql = "insert into account(name,money)values(?,?)";  jdbcTemplate.update(sql, account.getName(), account.getMoney()); } public void delete(Integer id) {  String sql = "delete from account where id = ?";  jdbcTemplate.update(sql, id); } public void update(Account account) {  String sql = "update account set name = ? , money = ? where id = ?";  jdbcTemplate.update(sql, account.getName(), account.getMoney(), account.getId()); } public String findNameById(Integer id) {  String sql = "select name from account where id = ? ";  //单字段查询可以使用专用的查询方法,必须制定查询出的数据类型,例如name为String类型  return jdbcTemplate.queryForObject(sql, String.class, id); } public Account findById(Integer id) {  String sql = "select * from account where id = ? ";  //支持自定义行映射解析器  //RowMapper<Account> rm = new RowMapper<Account>() {  // public Account mapRow(ResultSet rs, int rowNum) throws SQLException {  //  Account account = new Account();  //  account.setId(rs.getInt("id"));  //  account.setName(rs.getString("name"));  //  account.setMoney(rs.getDouble("money"));  //  return account;  // }  //};  //return jdbcTemplate.queryForObject(sql, rm, id);  return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Account>(Account.class), id); } public List<Account> findAll() {  String sql = "select * from account";  //使用spring自带的行映射解析器,要求必须是标准封装  return jdbcTemplate.query(sql,    new BeanPropertyRowMapper<Account>(Account.class)); } public List<Account> findAll(int pageNum, int pageSize) {  String sql = "select * from account limit ?,?";  //分页数据通过查询参数赋值  return jdbcTemplate.query(sql,    new BeanPropertyRowMapper<Account>(Account.class),    (pageNum - 1) * pageSize,    pageSize); } public Long getCount() {  String sql = "select count(id) from account ";  //单字段查询可以使用专用的查询方法,必须制定查询出的数据类型,例如数据总量为Long类型  return jdbcTemplate.queryForObject(sql, Long.class); }}

     

  3. 测试AccountService中的所有方法

    //设定spring专用的类加载器@RunWith(SpringJUnit4ClassRunner.class)//设定加载的spring上下文对应的配置@ContextConfiguration(classes = SpringConfig.class)public class AccountServiceTest { @Autowired private AccountService accountService; @Test public void testSave() {  Account account = new Account();  account.setName("阿尔萨斯");  account.setMoney(999.99d);  accountService.save(account); } @Test public void testDelete() {  accountService.delete(21); } @Test public void testUpdate() {  Account account = new Account();  account.setId(13);  account.setName("itheima");  account.setMoney(6666666666.66d);  accountService.update(account); } @Test public void testFindNameById() {  String name = accountService.findNameById(13);  System.out.println(name); } @Test public void testFindById() {  Account account = accountService.findById(13);  System.out.println(account); } @Test public void testFindAll() {  List<Account> list = accountService.findAll();  System.out.println(list); } @Test public void testFindAll1() {  List<Account> list = accountService.findAll(2, 2);  System.out.println(list); } @Test public void testGetCount() {  Long count = accountService.getCount();  System.out.println(count); }}

     

3.3)NamedParameterJdbcTemplate

提供标准的具名sql语句操作API

  1. 编写新的AccountDao实现类:AccountDaoImpl2

    //dao注册为bean@Repository("accountDao2")@Primarypublic class AccountDaoImpl2 implements AccountDao { //注入模板对象 @Autowired private NamedParameterJdbcTemplate jdbcTemplate; public void save(Account account) {  System.out.println(this.getClass().getName());  String sql = "insert into account(name,money)values(:name,:money)";  Map pm = new HashMap();  pm.put("name",account.getName());  pm.put("money",account.getMoney());  System.out.println("NamedParameterJdbcTemplate");  jdbcTemplate.update(sql,pm); } public void delete(Integer id) { } public void update(Account account) { } public String findNameById(Integer id) {  return null; } public Account findById(Integer id) {  return null; } public List<Account> findAll() {  return null; } public List<Account> findAll(int pageNum, int preNum) {  return null; } public Long getCount() {  return null; }}

     

  2. 测试NamedParameterJdbcTemplate使用

    //设定spring专用的类加载器@RunWith(SpringJUnit4ClassRunner.class)//设定加载的spring上下文对应的配置@ContextConfiguration(classes = SpringConfig.class)public class AccountServiceTest { @Autowired private AccountService accountService; @Test public void testSave() {  Account account = new Account();  account.setName("阿尔萨斯");  account.setMoney(999.99d);  accountService.save(account); }}

     

     

     

     

3.4)RedisTemplate(了解)

3.4.1)环境准备-视频12

  1. 配置redis.conf

    bind 0.0.0.0port 6379protected-mode no

     

  2. 启动Redis

    • Linux

      redis-server redis.conf

       

    • Windows:打开Redis安装目录,双击redis-server.exe

  3. 使用Redis控制台

    #打开Redis控制台: Linux
    redis-cli

     

    #打开Redis控制台: Windows#双击redis-cli.exe

     

3.4.2)对象结构-视频13

RedisTemplate提供的方法主要分为如下4类:

  • 客户端基本操作 

 

 

  • 常用:Operations具体数据类型操作 

 

 

 

public void changeMoney(Integer id, Double money) { redisTemplate.opsForValue().set("account:id:"+id,money);}public Double findMondyById(Integer id) { Object money = redisTemplate.opsForValue().get("account:id:" + id); return new Double(money.toString());}

 

  • Bound Operations阻塞式数据类型操作 

 

 

其他操作 

 

 

3.4.3 使用RedisTemplate

  1. 在resources目录下新建redis.properties

    # redis服务器主机地址redis.host=127.0.0.1#redis服务器主机端口redis.port=6379

     

    #redis服务器登录密码#redis.password=itheima#最大活动连接redis.maxActive=20#最大空闲连接redis.maxIdle=10#最小空闲连接redis.minIdle=0#最大等待时间redis.maxWait=-1

     

  2. 新建RedisConfig配置类:com.itheima.config

    package com.itheima.config;@PropertySource("redis.properties")public class RedisConfig { @Value("${redis.host}") private String hostName; @Value("${redis.port}") private Integer port;// @Value("${redis.password}")// private String password; @Value("${redis.maxActive}") private Integer maxActive; @Value("${redis.minIdle}") private Integer minIdle; @Value("${redis.maxIdle}") private Integer maxIdle; @Value("${redis.maxWait}") private Integer maxWait;

     

    @Bean //配置RedisTemplate public RedisTemplate createRedisTemplate(RedisConnectionFactory redisConnectionFactory){  //1.创建对象  RedisTemplate redisTemplate = new RedisTemplate();  //2.设置连接工厂  redisTemplate.setConnectionFactory(redisConnectionFactory);  //3.设置redis生成的key的序列化器,对key编码进行处理  RedisSerializer stringSerializer = new StringRedisSerializer();  redisTemplate.setKeySerializer(stringSerializer);  redisTemplate.setHashKeySerializer(stringSerializer);  //4.返回  return redisTemplate; }

     @Bean //配置Redis连接工厂 public RedisConnectionFactory createRedisConnectionFactory(RedisStandaloneConfiguration redisStandaloneConfiguration,GenericObjectPoolConfig genericObjectPoolConfig){  //1.创建配置构建器,它是基于池的思想管理Jedis连接的  JedisClientConfiguration.JedisPoolingClientConfigurationBuilder builder = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder)JedisClientConfiguration.builder();  //2.设置池的配置信息对象  builder.poolConfig(genericObjectPoolConfig);  //3.创建Jedis连接工厂  JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration,builder.build());  //4.返回  return jedisConnectionFactory; } @Bean //配置spring提供的Redis连接池信息 public GenericObjectPoolConfig createGenericObjectPoolConfig(){  //1.创建Jedis连接池的配置对象  GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();  //2.设置连接池信息  genericObjectPoolConfig.setMaxTotal(maxActive);  genericObjectPoolConfig.setMinIdle(minIdle);  genericObjectPoolConfig.setMaxIdle(maxIdle);  genericObjectPoolConfig.setMaxWaitMillis(maxWait);  //3.返回  return genericObjectPoolConfig; }

     

     @Bean //配置Redis标准连接配置对象 public RedisStandaloneConfiguration createRedisStandaloneConfiguration(){  //1.创建Redis服务器配置信息对象  RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();  //2.设置Redis服务器地址,端口和密码(如果有密码的话)  redisStandaloneConfiguration.setHostName(hostName);  redisStandaloneConfiguration.setPort(port);//  redisStandaloneConfiguration.setPassword(RedisPassword.of(password));  //3.返回  return redisStandaloneConfiguration; }}

     

  3. AccountService

    public interface AccountService { void changeMoney(Integer id,Double money); Double findMoneyById(Integer id);}

     

  4. AccountServiceImpl:使用redis实现changeMoney和findMoneyById

    @Service("accountService")public class AccountServiceImpl implements AccountService { @Autowired private RedisTemplate redisTemplate; public void changeMoney(Integer id, Double money) {  //等同于redis中set account:id:1 100  redisTemplate.opsForValue().set("account:id:"+id, money); } public Double findMoneyById(Integer id) {  //等同于redis中get account:id:1  Object money = redisTemplate.opsForValue().get("account:id:"+id);  return new Double(money.toString()); }}

     

  5. 编写单元测试:AccountServiceTest

    //设定spring专用的类加载器@RunWith(SpringJUnit4ClassRunner.class)//设定加载的spring上下文对应的配置@ContextConfiguration(classes = SpringConfig.class)public class AccountServiceTest { @Autowired private AccountService accountService; @Test public void test(){  Jedis jedis = new Jedis("127.0.0.1",6379);  jedis.set("name","itheima");  System.out.println(jedis.get("name"));  jedis.close(); } @Test public void changeMoney() {  accountService.changeMoney(1,100D); } @Test public void findMoneyById() {  Double money = accountService.findMoneyById(1);  System.out.println(money); }}

     

4)模板对象原理解析

4.1)策略模式-视频14

完成一项任务往往可以有多种不同的方式,每一种方式称为一个策略,我们可以根据环境或者条件的不同选择不同的策略来完成该项务。

策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。

 

 

应用场景如下:

 

 

4.2)装饰模式应用

装饰模式在不改变原有设计基础上,对方法进行了增强。

  • JdbcTemplatepublic void save(Account account) { String sql = "insert into account(name,money)values(?,?)"; jdbcTemplate.update(sql, account.getName(), account.getMoney());}

     

  • NamedParameterJdbcTemplatepublic void save(Account account) { System.out.println(this.getClass().getName()); String sql = "insert into account(name,money)values(:name,:money)"; Map pm = new HashMap(); pm.put("name",account.getName()); pm.put("money",account.getMoney()); System.out.println("NamedParameterJdbcTemplate"); jdbcTemplate.update(sql,pm);}

     









原文转载:http://www.shaoqun.com/a/619655.html

跨境电商:https://www.ikjzd.com/

雨果:https://www.ikjzd.com/w/1307

塔图:https://www.ikjzd.com/w/2274


spring事务:事务控制方式,使用AOP控制事务,七种事务传播行为,声明事务,模板对象,模板对象原理分析知识点梳理课堂讲义1)事务回顾1.1)什么是事务-视频01事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败。1.2)事务的作用事务特征(ACID)原子性(Atomicity)指事务是一个不可分割的整体,其中的操作要么全执行或全不执行一致性(Consisten
萌店:https://www.ikjzd.com/w/1538
手机trademanager:https://www.ikjzd.com/w/730
patpat:https://www.ikjzd.com/w/1079
速卖通运营:怎样有效提高店铺订单转化率?:https://www.ikjzd.com/home/96245
OzBargain:https://www.ikjzd.com/w/2019
超级干货:100个国家快递攻略大全教你用什么快递清关容易又便宜:https://www.ikjzd.com/home/12692