public static int getKeyStringCount(String str, String key){
int count = 0;
int index = 0;
while((index = str.indexOf(key,index)) > 0){
index = index + key.length();
count++;
}
return count;
}
(3)、两个字符串中最大相同的子串
public static void main(String[] args){
String s1 = "jskkskabcdlslslsl";
String s2 = "xjxabcdjas";
String s = getMaxSubstring(s1, s2);
System.out.println("s="+s);
}
public static String getMaxSubstring(String s1, String s2){
String max = null, min = null;
max = (s1.length()>s2.length())?s1:s2;
min = max.equals(s1)?s2:s1;
for(int i=0; i<min.length(); i++){
for(int a=0, b=s2.length()-i; b!=s2.length()+1, a++, b++){
String sub = s2.subString(a, b);
if(s1.contains(sub))
return sub;
}
}
return null;
}
class StopThread implements Runnable{
private boolean flag = true;
public void run(){
while(flag){
System.out.println(Thread.currentThread().getName()+"...");
}
}
public void setFlag(){
flag = false;
}
}
class StopThreadDemo{
public static void main(String[] args){
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.start();
t2.start();
int num = 1;
for(;;){
if(++num == 50){
st.setFlag(0;
break;
}
System.out.println("main..."+num);
}
System.out.println("over");
}
}
class Demo implements Runnable{
public void run(){
show();
}
public void show(){
for(int x=0; x<20; x++){
system.out.println(Thread.currentThread().getname()+"........"+x);
}
}
}
class TreadDemo{
public static void main(sting[] args){
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start;
t2.start;
}
}
线程安全隐患排查原则
1、查找共享数据
2、共享数据代码的操作不止一条
事例:两个储户到银行存钱,每次存100,共存三次。银行总数从100到600递增。
class Bank{
private int sum;
public void add(int num){
sum = sum + num;
try{
Thread.sleep();
}catch(InterruptedException e){
//...
}
System.out.println("sum="+sum);
}
}
class Cus implements Runnable{
private b = new Bank();
public void run(){
for(int x=0; x<3; x++){
b.add(100);
}
}
}
class BankDemo{
public static void main(String[] args){
Cus c = new Cus();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}
class Bank{
private int sum;
private Object obj = new Object();
public void add(int num){
synchronized(obj){//三个线程共用一个对象锁obj
sum = sum + num;
try{
Thread.sleep();
}catch(InterruptedException e){
//...
}
System.out.println("sum="+sum);
}
}
}
解决方式二:
同步函数
class Bank{
private int sum;
public synchronized void add(int num){//同步函数
sum = sum + num;
try{
Thread.sleep();
}catch(InterruptedException e){
//...
}
System.out.println("sum="+sum);
}
}
同步的好处和弊端
好处:解决了线程的安全问题
弊端:降低了效率,因为同步外的线程都会判断同步锁。
同步函数和同步代码块的区别:
1、同步函数使用的锁是this,同步代码块的锁是任意的对象。
2、建议使用同步代码块。
静态同步函数的锁
静态同步函数的锁是该函数所属的字节码文件对象
该对象可以用this.getClass()方法获取,也可以用当前类名.class获取。
class Bank{
private int sum;
public static synchronized void add(int num){
sum = sum + num;
try{
Thread.sleep();
}catch(InterruptedException e){
//...
}
System.out.println("sum="+sum);
}
}
该静态同步函数add的同步锁即为该函数所属的字节码文件对象,即为Bank.class。
单例模式涉及的多线程问题
//饿汉式
class Single{
private static final Singles = new Single();
private Single(){};
public static Single getInstance(){
return s;
}
}
//懒汉式
class Single{
private static final Singles = null;
private Single(){};
public static Single getInstance(){
if(s == null)
s = new Single();
return s;
}
}
class SingleDemo{
public static void main(String[] args){
}
}
class Test implements Runnable{
private boolean flag = true;
public void run(){
if(flag){
while(true)
synchronized(MyLock.locka){
System.out.prinln(Thread.currentThread().getName()+"if...locka...");
synchronized(MyLock.lockb){
System.out.prinln(Thread.currentThread().getName()+"if...lockb...");
}
}
}else{
while(true)
synchronized(MyLock.lockb){
System.out.prinln(Thread.currentThread().getName()+"else...lockb...");
synchronized(MyLock.locka){
System.out.prinln(Thread.currentThread().getName()+"else...locka...");
}
}
}
}
}
class MyLock{
public static final Object locka = new Object();
public static final Object lockb = new Object();
}
class DeadLockTest{
public static void main(String[] args){
Test a = new Test();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.start();
try{
Thread.sleep(10);//冻结main主线程10毫秒
}catch(){
//...
}
a.flag = false;
t2.start();
}
}
<!-- Stack the columns on mobile by making one full-width and the other half-width -->
<div class="row">
<div class="col-xs-12 col-md-8">.col-xs-12 .col-md-8</div>
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
</div>
<!-- Columns start at 50% wide on mobile and bump up to 33.3% wide on desktop -->
<div class="row">
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
<div class="col-xs-6 col-md-4">.col-xs-6 .col-md-4</div>
</div>
<!-- Columns are always 50% wide, on mobile and desktop -->
<div class="row">
<div class="col-xs-6">.col-xs-6</div>
<div class="col-xs-6">.col-xs-6</div>
</div>
ele - 指令的jQLite(jQuery的子集)包装DOM元素。如果你在引入AngularJS之前引入了jQuery,那么这个元素就是jQuery元素,而不是jQLite元素。由于这个元素已经被jQuery/jQLite包装了,所以我们就在进行DOM操作的时候就不需要再使用 $()来进行包装。
attr - 一个包含了指令所在元素的属性的标准化的参数对象。举个例子,你给一个HTML元素添加了一些属性:,那么可以在 link 函数中通过 attrs.someAttribute 来使用它。
link函数主要用来为DOM元素添加事件监听、监视模型属性变化、以及更新DOM。
在上面的指令代码片段中,我们添加了两个事件, click,和 mouseover。click 处理函数用来重置的背景色,而 mouseover 处理函数改变鼠标为 pointer。在模板中有一个表达式 {color},当父scope中的 color 发生变化时,它用来改变 Hello World 文字的背景色。 这个plunker演示了这些概念
4、compile函数
compile 函数在 link 函数被执行之前用来做一些DOM改造。它接收下面的参数:
tElement – 指令所在的元素
attrs – 元素上赋予的参数的标准化列表
要注意的是 compile 函数不能访问 scope,并且必须返回一个 link 函数。但是如果没有设置 compile 函数,你可以正常地配置 link 函数,(有了compile,就不能用link,link函数由compile返回)。compile函数可以写成如下的形式:
app.directive('test', function() {
return {
compile: function(tElem,attrs) {
//do optional DOM transformation here
return function(scope,elem,attrs) {
//linking function here
};
}
};
});
大多数的情况下,你只需要使用 link 函数。这是因为大部分的指令只需要考虑注册事件监听、监视模型、以及更新DOM等,这些都可以在 link 函数中完成。 但是对于像 ng-repeat 之类的指令,需要克隆和重复 DOM 元素多次,在 link 函数执行之前由 compile 函数来完成。这就带来了一个问题,为什么我们需要两个分开的函数来完成生成过程,为什么不能只使用一个?要回答好这个问题,我们需要理解指令在Angular中是如何被编译的!
app.directive('outerDirective', function() {
return {
scope: {},
restrict: 'AE',
controller: function($scope, $compile, $http) {
// $scope is the appropriate scope for the directive
this.addChild = function(nestedDirective) { // this refers to the controller
console.log('Got the message from nested directive:' + nestedDirective.message);
};
}
};
});
1、问题:Template for directive ‘rabbitFooter’ must have exactly one root element
控制台报错:angular.js?bust=1463908350577:13550 Error: [$compile:tplrt] Template for directive ‘rabbitFooter’ must have exactly one root element. ../../../template/tplIndex/rabbitFooter.html