中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JAVA中native方法與synchronized 關鍵字

發布時間:2020-08-10 11:58:46 來源:ITPUB博客 閱讀:415 作者:jasonhero 欄目:編程語言

native , synchronized

[@more@]

JAVA中native方法
@與羊共舞的狼

Java不是完美的,Java的不足除了體現在運行速度上要比傳統的C++慢許多之外,Java無法直接訪問到操

作系統底層(如系統硬件等),為此Java使用native方法來擴展Java程序的功能。
  可以將native方法比作Java程序同C程序的接口,其實現步驟:
  1、在Java中聲明native()方法,然后編譯;
  2、用javah產生一個.h文件;
  3、寫一個.cpp文件實現native導出方法,其中需要包含第二步產生的.h文件(注意其中又包含了

JDK帶的jni.h文件);
  4、將第三步的.cpp文件編譯成動態鏈接庫文件;
  5、在Java中用System.loadLibrary()方法加載第四步產生的動態鏈接庫文件,這個native()方法就

可以在Java中被訪問了。

JAVA本地方法適用的情況 1.為了使用底層的主機平臺的某個特性,而這個特性不能通過JAVA API訪問

2.為了訪問一個老的系統或者使用一個已有的庫,而這個系統或這個庫不是用JAVA編寫的

3.為了加快程序的性能,而將一段時間敏感的代碼作為本地方法實現。

首先寫好JAVA文件
/*
* Created on 2005-12-19 Author shaoqi
*/
package com.hode.hodeframework.modelupdate;

public class CheckFile
{
public native void displayHelloWorld();

static
{
System.loadLibrary("test");
}

public static void main(String[] args) {
new CheckFile().displayHelloWorld();
}
}
然后根據寫好的文件編譯成CLASS文件
然后在classes或bin之類的class根目錄下執行javah -jni

com.hode.hodeframework.modelupdate.CheckFile,
就會在根目錄下得到一個com_hode_hodeframework_modelupdate_CheckFile.h的文件
然后根據頭文件的內容編寫com_hode_hodeframework_modelupdate_CheckFile.c文件
#include "CheckFile.h"
#include
#include

JNIEXPORT void JNICALL Java_com_hode_hodeframework_modelupdate_CheckFile_displayHelloWorld

(JNIEnv *env, jobject obj)
{
printf("Hello world!n");
return;
}
之后編譯生成DLL文件如“test.dll”,名稱與System.loadLibrary("test")中的名稱一致
vc的編譯方法:cl -I%java_home%include -I%java_home%includewin32 -LD

com_hode_hodeframework_modelupdate_CheckFile.c -Fetest.dll
最后在運行時加參數-Djava.library.path=[dll存放的路徑]

********************************************************************************************

synchronized 關鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。
1. synchronized 方法:通過在方法聲明中加入 synchronized關鍵字來聲明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制對類成員變量的訪問:每個類實例對應一把鎖,每個 synchronized 方法都必須

獲得調用該方法的類實例的鎖方能執行,否則所屬線程阻塞,方法一旦執行,就獨占該鎖,直到從該方法

返回時才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進入可執行狀態。這種機制確保了同一時刻對

于每一個類實例,其所有聲明為 synchronized 的成員函數中至多只有一個處于可執行狀態(因為至多只

有一個能夠獲得該類實例對應的鎖),從而有效避免了類成員變量的訪問沖突(只要所有可能訪問類成員

變量的方法均被聲明為 synchronized)。
在 Java 中,不光是類實例,每一個類也對應一把鎖,這樣我們也可將類的靜態成員函數聲明為

synchronized ,以控制其對類的靜態成員變量的訪問。
synchronized 方法的缺陷:若將一個大的方法聲明為synchronized 將會大大影響效率,典型地,若將線

程類的方法 run() 聲明為 synchronized ,由于在線程的整個生命期內它一直在運行,因此將導致它對

本類任何 synchronized 方法的調用都永遠不會成功。當然我們可以通過將訪問類成員變量的代碼放到專

門的方法中,將其聲明為 synchronized ,并在主方法中調用來解決這一問題,但是 Java 為我們提供了

更好的解決辦法,那就是 synchronized 塊。
2. synchronized 塊:通過 synchronized關鍵字來聲明synchronized 塊。語法如下:
synchronized(syncObject) {
//允許訪問控制的代碼
}
synchronized 塊是這樣一個代碼塊,其中的代碼必須獲得對象 syncObject (如前所述,可以是類實例

或類)的鎖方能執行,具體機制同前所述。由于可以針對任意代碼塊,且可任意指定上鎖的對象,故靈活

性較高。

對synchronized(this)的一些理解(很細致,感謝作者!)

一、當兩個并發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能

有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以后才能執行該代碼塊。

二、然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該

object中的非synchronized(this)同步代碼塊。

三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object

中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

四、第三個例子同樣適用其它同步代碼塊。也就是說,當一個線程訪問object的一個synchronized(this)

同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪

問都被暫時阻塞。

五、以上規則對其它對象鎖同樣適用.

舉例說明:
一、當兩個并發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能

有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以后才能執行該代碼塊。

package ths;

public class Thread1 implements Runnable {
public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
tb.start();
}
}

結果:
A synchronized loop 0
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4

二、然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該

object中的非synchronized(this)同步代碼塊。

package ths;

public class Thread2 {
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final Thread2 myt2 = new Thread2();
Thread t1 = new Thread(
new Runnable() {
public void run() {
myt2.m4t1();
}
}, "t1"
);
Thread t2 = new Thread(
new Runnable() {
public void run() {
myt2.m4t2();
}
}, "t2"
);
t1.start();
t2.start();
}
}

結果:
t1 : 4
t2 : 4
t1 : 3
t2 : 3
t1 : 2
t2 : 2
t1 : 1
t2 : 1
t1 : 0
t2 : 0

三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object

中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

//修改Thread2.m4t2()方法:
public void m4t2() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}

}

結果:

t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0

四、第三個例子同樣適用其它同步代碼塊。也就是說,當一個線程訪問object的一個synchronized(this)

同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪

問都被暫時阻塞。

//修改Thread2.m4t2()方法如下:

public synchronized void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}

結果:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0

五、以上規則對其它對象鎖同樣適用:

package ths;

public class Thread3 {
class Inner {
private void m4t1() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
private void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized(inner) { //使用對象鎖
inner.m4t1();
}
}
private void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Thread3 myt3 = new Thread3();
final Inner inner = myt3.new Inner();
Thread t1 = new Thread(
new Runnable() {
public void run() {
myt3.m4t1(inner);
}
}, "t1"
);
Thread t2 = new Thread(
new Runnable() {
public void run() {
myt3.m4t2(inner);
}
}, "t2"
);
t1.start();
t2.start();
}
}

結果:

盡管線程t1獲得了對Inner的對象鎖,但由于線程t2訪問的是同一個Inner中的非同步部分。所以兩個線程

互不干擾。

t1 : Inner.m4t1()=4
t2 : Inner.m4t2()=4
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=3
t1 : Inner.m4t1()=2
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=0

現在在Inner.m4t2()前面加上synchronized:

private synchronized void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}

結果:

盡管線程t1與t2訪問了同一個Inner對象中兩個毫不相關的部分,但因為t1先獲得了對Inner的對象鎖,所

以t2對Inner.m4t2()的訪問也被阻塞,因為m4t2()是Inner中的一個同步方法。

t1 : Inner.m4t1()=4
t1 : Inner.m4t1()=3
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=4
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0


-----------------------------------------------------------------------------

2。 Java線程及同步(synchronized)樣例代碼

import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;

public class TestThread extends Thread
{
private static Integer threadCounterLock; //用于同步,防止數據被寫亂
private static int threadCount; //本類的線程計數器

static
{
threadCount = 0;
threadCounterLock = new Integer(0);
}

public TestThread()
{
super();
}

public synchronized static void incThreadCount()
{
threadCount++;
System.out.println("thread count after enter: " + threadCount);
}

public synchronized static void decThreadCount()
{
threadCount--;
System.out.println("thread count after leave: " + threadCount);
}

public void run()
{
synchronized(threadCounterLock) //同步
{
threadCount++;
System.out.println("thread count after enter: " + threadCount);
}

//incThreadCount(); //和上面的語句塊是等價的

final long nSleepMilliSecs = 1000; //循環中的休眠時間

long nCurrentTime = System.currentTimeMillis();
long nEndTime = nCurrentTime + 30000; //運行截止時間
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

try
{
while (nCurrentTime < nEndTime)
{
nCurrentTime = System.currentTimeMillis();
System.out.println("Thread " + this.hashCode() + ", current time: " +

simpleDateFormat.format(new Date(nCurrentTime)));

try
{
sleep(nSleepMilliSecs);
}
catch(InterruptedException ex)
{
ex.printStackTrace();
}
}
}
finally
{
synchronized(threadCounterLock) //同步
{
threadCount--;
System.out.println("thread count after leave: " + threadCount);
}

//decThreadCount(); //和上面的語句塊是等價的
}
}

public static void main(String[] args)
{
TestThread[] testThread = new TestThread[2];
for (int i=0; i{
testThread[i] = new TestThread();
testThread[i].start();
}
}
}

同步就是簡單的說我用的時候你不能用,大家用的要是一樣的就這樣!
比如說有只蘋果很好吃,我拉起來咬一口,放下,你再拉起咬一口,這就同步了,要是大家一起咬,呵呵

,那就結婚吧,婚禮上常能看到這個,也不怕咬著嘴,嘻嘻嘻!

舉個例子,現在有個類,類中有一個私有成員一個蘋果,兩個方法一個看,一個吃。
現在不同步,我一“看”,哈哈一個蘋果,我“吃”四分之一了
你一“看”,哈哈一個蘋果,也“吃”四分之一了。
可能的情況就是都是看到一個蘋果但我的吃方法用在你的之前,所以可能你只能吃到3/4的1/4也就是3/16

個而不是1/4個蘋果了。
現在加入同步鎖,我在吃的時候你看被鎖,等吃完了,你再看,啊3/4個蘋果,吃1/3好了了,就這樣!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

潞城市| 临武县| 吴旗县| 灌南县| 东乡县| 通辽市| 新和县| 武城县| 大安市| 晋城| 莱阳市| 寻甸| 怀安县| 钟祥市| 城固县| 收藏| 松原市| 林州市| 民勤县| 拉萨市| 体育| 枣强县| 滦平县| 邮箱| 六枝特区| 阿勒泰市| 南丹县| 老河口市| 汤原县| 女性| 商水县| 郯城县| 贵溪市| 忻州市| 南郑县| 白城市| 平凉市| 怀宁县| 伊宁县| 吴桥县| 三门县|