【问题标题】:How can i make the c function wait before the synchronised method finishes its work?如何让 c 函数在同步方法完成其工作之前等待?
【发布时间】:2012-05-11 06:38:54
【问题描述】:

以下 java 代码沿主线程创建 2 个线程。在创建的 2 个线程上,调用了一个执行 I/O 函数的 C 函数。然后从主线程调用另一个 C 函数 (againCallReadFile),然后调用 firstThread 方法。这个先前调用的方法很可能正在休眠或仍在工作。现在我如何确保在它返回或完成它的工作后我调用它synchronised method

Java 代码:

package Package;


public class Multithreading {

private native void readFile();
private native void writeFile();
private native void againCallReadFile();

public static void main(String args[]) {
    Multithreading.firstThread(); 
    Multithreading.secondThread();
    // the above functions sleep for 15 seconds
    new Multithreading().againCallReadFile(); // WILL GIVE THE FATAL ERROR ! B'COZ THAT METHOD SLEEPS FOR 15 SECONDS AFTER IT IS CALLED.
}

public synchronized static void firstThread() {
    Runnable r = new Runnable() {
        @Override
        public void run() {
            System.out.println("First Thread Started at " + new java.util.Date());
            System.out.println();
            new Multithreading().readFile();
            try {
                Thread.sleep(15 * 1000); // sleep for 15 seconds
            } catch(Exception exc) {
                exc.printStackTrace();
            }
        }
    };
    new Thread(r,"FirstThread").start();
}

public synchronized static void secondThread() {
    Runnable r = new Runnable() {
        @Override
        public void run() {
            System.out.println("Second Thread Started at " + new java.util.Date());
            System.out.println();
            new Multithreading().writeFile();
            try {
                Thread.sleep(15 * 1000); // sleep for 15 seconds
            }catch(Exception exc) {
                exc.printStackTrace();
            }
        }
    };
    new Thread(r,"Second Thread").start();
}

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

C 代码:

#include "stdio.h"
#include "string.h"
#include "Package_Multithreading.h"

/*
 * Class:     Package_Multithreading
 * Method:    readFile
 * Signature: ()V
 */

void Java_Package_Multithreading_readFile
  (JNIEnv *env, jobject obj) { // function that reads a file

 printf("In the C method that reads file!\n");
 FILE *f_open = fopen("c_io/file_r.txt","r");
 fseek(f_open,0,SEEK_END);
 long lSize = ftell(f_open);
 rewind(f_open);
 // allocate memory to contain whole file
 char *buffer = (char*)malloc(sizeof(char)*lSize);
 size_t result = fread(buffer,1,lSize,f_open); // file is now loaded in the memory buffer
 int i = 0;
 for(i=0;i<strlen(buffer);i++) {
    printf("%c",buffer[i]);
 }
 fclose(f_open);
}

/*
 * Class:     Package_Multithreading
 * Method:    writeFile
 * Signature: ()V
 */

void Java_Package_Multithreading_writeFile
  (JNIEnv *env, jobject obj) { // function that writes a file

 printf("In the C method that writes to the file !\n");
 char buffer[] = "This data is a result of JNI !";
 FILE *f_open = fopen("c_io/file_w.txt","wb");
 int x = fwrite(buffer,1,sizeof(buffer),f_open);
 fclose(f_open);
 printf("Data has been written to the file !");
}

void Java_Package_Multithreading_againCallReadFile
  (JNIEnv *env, jobject obj) { // function that calls the already called synchronised method

  // The following snippet calls the function firstThread of java that could be sleeping. It sleeps for 15 seconds !

  jclass cls = (*env)->GetObjectClass(env,obj);
  jmethodID mid = (*env)->GetMethodID(env,cls,"firstThread","()V");
  (*env)->CallVoidMethod(env,obj,mid); // call the synchronized method that sleeps for 5 minutes !
}

如何使Java_Package_Multithreading_againCallReadFile 中的代码等到java 中的firstThread 方法完成,或者有什么方法可以知道在调用同步函数之前我必须等待?

【问题讨论】:

  • 是的,我们不会阅读所有内容。
  • 请问你为什么用C写文件?无论如何,编写文件的大部分工作都是由操作系统完成的......
  • @Renato 正在测试一些东西..没什么重要的

标签: java c multithreading java-native-interface


【解决方案1】:

我更喜欢在 java 端实现同步,而不是在 C 端。您可以使用 lock 进行同步:

    private static final Lock lock = new ReentalLock();

    public static void firstThread() {
        final CountDownLatch waitToFinishLatch = new CountDownLatch(1);
        Runnable r = new Runnable() {
            @Override
            public void run() {            
                try {
                    // Will wait until other thread call unloak or if no lock was called:
                    lock.lock();
                    System.out.println("First Thread Started at " + new java.util.Date());
                    System.out.println();
                    new Multithreading().readFile();
                    try {
                        Thread.sleep(15 * 1000); // sleep for 15 seconds
                    } catch(Exception exc) {
                        exc.printStackTrace();
                    }
                } finally {
                    lock.unlock();
                    waitToFinishLatch.countDown();
                }
            }
        };
        new Thread(r,"FirstThread").start();
        try {
            // Here we are waiting for thread to be finish
            waitToFinishLatch.await();
        } catch(InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public synchronized static void secondThread() {
        final CountDownLatch waitToFinishLatch = new CountDownLatch(1);
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    // Will wait until other thread call unloak or if no lock was called:
                    lock.lock();
                    System.out.println("Second Thread Started at " + new java.util.Date());
                    System.out.println();
                    new Multithreading().writeFile();
                    try {
                        Thread.sleep(15 * 1000); // sleep for 15 seconds
                    }catch(Exception exc) {
                        exc.printStackTrace();
                } finally {
                    lock.unlock();
                    waitToFinishLatch.countDown();
                }
            }
        }
        try {
            // Here we are waiting for thread to be finish
            waitToFinishLatch.await();
        } catch(InterruptedException e) {
            throw new RuntimeException(e);
        }
    };
    new Thread(r,"Second Thread").start();
}

在这种情况下,线程将相互等待。

【讨论】:

  • 在这种情况下会有什么帮助!
  • @program-o-steve:添加 CountDown 锁存器以等待线程完成。这会有帮助吗?
猜你喜欢
  • 2021-01-07
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 2021-04-16
  • 1970-01-01
  • 1970-01-01
  • 2020-01-15
  • 1970-01-01
相关资源
最近更新 更多