Please let me know below method invocation is thread safe or not.
I am calling ThreadStartMain on my main thread and create new threads and invoke A_GetCounryName method on new instance.
Since i am always calling via new instance i think this is thread safe even though i am having instance variables in some classes.
class MyThread
{
private void ThreadStartMain()
{
for (int i = 0; i < 5; i++)
{
A a = new A();
ThreadStart start = new ThreadStart(a.A_GetCounryName);
Thread t = new Thread(start);
t.Start();
}
}
}
class A
{
public B GetNewObject()
{
B bObj = new B();
return bObj;
}
public void A_GetCounryName()
{
B b=GetObject();
string cName=b.B_GetCoutryName();
}
}
class B
{
C cObj = null;
public B()
{
cObj = new C();
cObj.Prop1 = 1;
cObj.Prop1 = 2;
cObj.Prop1 = 3;
}
public string B_GetCoutryName()
{
string countryName= cObj.C_GetCoutryName();
return countryName;
}
}
class C
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
public int Prop3 { get; set; }
public string C_GetCoutryName()
{
string name = "Italy";
return name;
}
}
Yes, this is safe because your threads do not share state. More precisely: They do not access common storage locations.
Related
I am reading java 8 in action and the author references this link: http://mail.openjdk.java.net/pipermail/lambda-dev/2013-November/011516.html
and writes his own stream forker that looks like this:
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Main {
public static void main(String... args) {
List<Person> people = Arrays.asList(new Person(23, "Paul"), new Person(24, "Nastya"), new Person(30, "Unknown"));
StreamForker<Person> forker = new StreamForker<>(people.stream())
.fork("All names", s -> s.map(Person::getName).collect(Collectors.joining(", ")))
.fork("Age stats", s -> s.collect(Collectors.summarizingInt(Person::getAge)))
.fork("Oldest", s -> s.reduce((p1, p2) -> p1.getAge() > p2.getAge() ? p1 : p2).get());
Results results = forker.getResults();
String allNames = results.get("All names");
IntSummaryStatistics stats = results.get("Age stats");
Person oldest = results.get("Oldest");
System.out.println(allNames);
System.out.println(stats);
System.out.println(oldest);
}
interface Results {
<R> R get(Object key);
}
static class StreamForker<T> {
private final Stream<T> stream;
private final Map<Object, Function<Stream<T>, ?>> forks = new HashMap<>();
public StreamForker(Stream<T> stream) {
this.stream = stream;
}
public StreamForker<T> fork(Object key, Function<Stream<T>, ?> f) {
forks.put(key, f);
return this;
}
public Results getResults() {
ForkingStreamConsumer<T> consumer = build();
try {
stream.sequential().forEach(consumer);
} finally {
consumer.finish();
}
return consumer;
}
private ForkingStreamConsumer<T> build() {
List<BlockingQueue<T>> queues = new ArrayList<>();
Map<Object, Future<?>> actions =
forks.entrySet().stream().reduce(
new HashMap<>(),
(map, e) -> {
map.put(e.getKey(),
getOperationResult(queues, e.getValue()));
return map;
},
(m1, m2) -> {
m1.putAll(m2);
return m1;
}
);
return new ForkingStreamConsumer<>(queues, actions);
}
private Future<?> getOperationResult(List<BlockingQueue<T>> queues,
Function<Stream<T>, ?> f) {
BlockingQueue<T> queue = new LinkedBlockingQueue<>();
queues.add(queue);
Spliterator<T> spliterator = new BlockingQueueSpliterator<>(queue);
Stream<T> source = StreamSupport.stream(spliterator, false);
return CompletableFuture.supplyAsync(() -> f.apply(source));
}
}
static class ForkingStreamConsumer<T> implements Results, Consumer<T> {
static final Object END_OF_STREAM = new Object();
private final List<BlockingQueue<T>> queues;
private final Map<Object, Future<?>> actions;
ForkingStreamConsumer(List<BlockingQueue<T>> queues,
Map<Object, Future<?>> actions) {
this.queues = queues;
this.actions = actions;
}
public void finish() {
accept((T) END_OF_STREAM);
}
#Override
public <R> R get(Object key) {
try {
return ((Future<R>) actions.get(key)).get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
#Override
public void accept(T t) {
queues.forEach(q -> q.add(t));
}
}
static class BlockingQueueSpliterator<T> implements Spliterator<T> {
private final BlockingQueue<T> q;
public BlockingQueueSpliterator(BlockingQueue<T> q) {
this.q = q;
}
#Override
public boolean tryAdvance(Consumer<? super T> action) {
T t;
while (true) {
try {
t = q.take();
break;
} catch (InterruptedException e) {
}
}
if (t != ForkingStreamConsumer.END_OF_STREAM) {
action.accept(t);
return true;
}
return false;
}
#Override
public Spliterator<T> trySplit() {
return null;
}
#Override
public long estimateSize() {
return 0;
}
#Override
public int characteristics() {
return 0;
}
}
static class Person {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
#Override
public String toString() {
return String.format("Age: %d, name: %s", age, name);
}
}
}
How the code written by the author works:
First, we create a StreamForker out of a stream. Then we fork 3 operations, saying what we want to do on that stream in parallel. In our case, our data model is the Person{age, name} class and we want to perform 3 actions:
Get a string of all names
Get age statistics
Get the oldest person
we then call the forker.getResults() method, that applies a StreamForkerConsumer to the stream, spreading its elements into 3 blocking queues, which are then turned into 3 streams and processed in parallel.
My question is, does this approach have any advantage over just doing this:
Future<String> allNames2 =
CompletableFuture.supplyAsync(() -> people.stream().map(Person::getName).collect(Collectors.joining(", ")));
Future<IntSummaryStatistics> stats2 =
CompletableFuture.supplyAsync(() -> people.stream().collect(Collectors.summarizingInt(Person::getAge)));
Future<Person> oldest2 =
CompletableFuture.supplyAsync(() -> people.stream().reduce((p1, p2) -> p1.getAge() > p2.getAge() ? p1 : p2).get());
?
For me this doesn't make much sense with an array list as stream source.
If the stream source is a big file that you process with
StreamForker<Person> forker = new StreamForker<>(
java.nio.file.Files.lines(Paths.get("somepath"))
.map(Person::new))
.fork(...)
then it could prove beneficial since you would process the whole file only once, whereas with three seperat calls to Files.lines(...) you would read the file three times.
I want to create a new instance of a object which is holding a list object of another class.
public Class A
{
int a { get; set; };
List<B> b { get; set; }
}
public Class B
{
int c { get; set; };
}
public Class Test
{
A a= new A();
a.b= ? how to initiate this
a.b.c=some value;
}
I am not getting this value c here.how to get This value.
Try it this way:
public Class A
{
public int a { get; set; };
public List<B> b { get; set; }
public A()
{
b = new List<B>();
}
}
public Class B
{
public int c { get; set; };
}
public Class Test
{
A a= new A();
a.b= ? how to initiate this
a.b.Add(new B(){c = 13};
}
1.Try this initializing method
A objA = new A();
objA.a = 10;
objA.b = new List<B> { new B { C = 20 }, new B { C = 40 }, new B { C = 50 }, new B { C = 60 } };
2.Or try this one
A objA = new A();
objA.a = 10;
List<B> bList = new List<B>();
bList.Add(new B { C = 20 });
bList.Add(new B { C = 40 });
bList.Add(new B { C = 50 });
bList.Add(new B {C=60});
objA.b = bList;
And modify access specifiers of properties.
I am trying to implement a busy waiting mechanism, using 2 flags. I get a deadlock, but just can't understand why... it looks to me as if it should work...
sorry for the long code, That's the shortest I succeeded to make it.
package pckg1;
public class MainClass {
public static void main(String[] args) {
Buffer b = new Buffer();
Producer prod = new Producer(b);
Consumer cons = new Consumer(b);
cons.start();
prod.start();
}
}
class Producer extends Thread {
private Buffer buffer;
public Producer(Buffer buffer1) {
buffer = buffer1;
}
public void run() {
for (int i = 0; i < 60; i++) {
while (!buffer.canUpdate)
;
buffer.updateX();
buffer.canUpdate = false;
buffer.canUse = true;
}
}
}
class Consumer extends Thread {
private Buffer buffer;
public Consumer(Buffer buffer1) {
buffer = buffer1;
}
public void run() {
for (int i = 0; i < 60; i++) {
while (!buffer.canUse)
;
buffer.consumeX();
buffer.canUse = false;
buffer.canUpdate = true;
}
}
}
class Buffer {
private int x;
public boolean canUpdate;
public boolean canUse;
public Buffer() {
x = 0;
canUpdate = true;
}
public void updateX() {
x++;
System.out.println("updated to " + x);
}
public void consumeX() {
System.out.println("used " + x);
}
}
I recommend that all the logic concerning Buffer should go into that class.
Also, accessing (and modifying) the flags must be protected, if 2 or more have access to it. That's why I put synchronised to the 2 methods.
class Buffer {
private int x;
private boolean canUpdate;
private boolean canUse;
public Buffer() {
x = 0;
canUpdate = true;
}
public synchronised void updateX() {
x++;
System.out.println("updated to " + x);
canUpdate = false;
canUse = true;
}
public synchronised void consumeX() {
System.out.println("used " + x);
canUpdate = true;
canUse = false;
}
public synchronised boolean canUse() {
return canUse;
}
public synchronised boolean canUpdate() {
return canUpdate;
}
}
Also, remove the canUpdate and canUse writes from the Producer and Consumer classes, and replace the reads (in the conditons) with the methods.
Also, it would be useful to introduce some Thread.sleep(100) in the waiting loops.
Just recently a few colleagues of mine helped out with narrowing down a memory leak. One of the problems was found in Microsoft's code. This is from reflector showing that the enumerator will leak.
Here the count property calls getenumerator but never checks for Idisposable:
public int Count
{
get
{
if (this.isDisposed)
{
throw new ObjectDisposedException(name);
}
int num = 0;
IEnumerator enumerator = this.GetEnumerator();
while (enumerator.MoveNext())
{
num++;
}
return num;
}
}
This is the ManagementObjectCollection's GetEnumerator just to show the type returned is a ManagementObjectEnumerator.
public ManagementObjectEnumerator GetEnumerator()
{
if (this.isDisposed)
{
throw new ObjectDisposedException(name);
}
if (!this.options.Rewindable)
{
return new ManagementObjectEnumerator(this, this.enumWbem);
}
IEnumWbemClassObject ppEnum = null;
int errorCode = 0;
try
{
errorCode = this.scope.GetSecuredIEnumWbemClassObjectHandler(this.enumWbem).Clone_(ref ppEnum);
if ((errorCode & 0x80000000L) == 0L)
{
errorCode = this.scope.GetSecuredIEnumWbemClassObjectHandler(ppEnum).Reset_();
}
}
catch (COMException exception)
{
ManagementException.ThrowWithExtendedInfo(exception);
}
if ((errorCode & 0xfffff000L) == 0x80041000L)
{
ManagementException.ThrowWithExtendedInfo((ManagementStatus) errorCode);
}
else if ((errorCode & 0x80000000L) != 0L)
{
Marshal.ThrowExceptionForHR(errorCode);
}
return new ManagementObjectEnumerator(this, ppEnum);
}
This showing that it is disposable:
public class ManagementObjectEnumerator : IEnumerator, IDisposable
{
// Fields
private bool atEndOfCollection;
private uint cachedCount;
private IWbemClassObjectFreeThreaded[] cachedObjects;
private int cacheIndex;
private ManagementObjectCollection collectionObject;
private IEnumWbemClassObject enumWbem;
private bool isDisposed;
private static readonly string name;
// Methods
static ManagementObjectEnumerator();
internal ManagementObjectEnumerator(ManagementObjectCollection collectionObject, IEnumWbemClassObject enumWbem);
public void Dispose();
protected override void Finalize();
public bool MoveNext();
public void Reset();
// Properties
public ManagementBaseObject Current { get; }
object IEnumerator.Current { [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get; }
}
Though enumerators that are disposable are disposed of properly by foreach statements (http://msdn.microsoft.com/en-us/library/aa664754(v=vs.71).aspx), this does not mean that the only case where the enumerator will be used is in a foreach loop.
I know that you can skip the count property and roll your own mechanism for getting the number of objects in the collection by using the enumerator yourself but the question I have is how much unmanaged memory does this leak?
We notice that inside of our .Net application we have contention when it comes to using SqlDataReader. While we understand that SqlDataReader is not ThreadSafe, it should scale. The following code is a simple example to show that we cannot scale our application because there is contention on the SqlDataReader GetValue method. We are not bound by CPU, Disk, or Network; Just the internal contention on the SqlDataReader. We can run the application 10 times with 1 thread and it scales linearly, but 10 threads in 1 app does not scale. Any thoughts on how to scale reading from SQL Server in a single c# application?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Globalization;
namespace ThreadAndSQLTester
{
class Host
{
/// <summary>
/// Gets or sets the receive workers.
/// </summary>
/// <value>The receive workers.</value>
internal List<Worker> Workers { get; set; }
/// <summary>
/// Gets or sets the receive threads.
/// </summary>
/// <value>The receive threads.</value>
internal List<Thread> Threads { get; set; }
public int NumberOfThreads { get; set; }
public int Sleep { get; set; }
public int MinutesToRun { get; set; }
public bool IsRunning { get; set; }
private System.Timers.Timer runTime;
private object lockVar = new object();
public Host()
{
Init(1, 0, 0);
}
public Host(int numberOfThreads, int sleep, int minutesToRun)
{
Init(numberOfThreads, sleep, minutesToRun);
}
private void Init(int numberOfThreads, int sleep, int minutesToRun)
{
this.Workers = new List<Worker>();
this.Threads = new List<Thread>();
this.NumberOfThreads = numberOfThreads;
this.Sleep = sleep;
this.MinutesToRun = minutesToRun;
SetUpTimer();
}
private void SetUpTimer()
{
if (this.MinutesToRun > 0)
{
this.runTime = new System.Timers.Timer();
this.runTime.Interval = TimeSpan.FromMinutes(this.MinutesToRun).TotalMilliseconds;
this.runTime.Elapsed += new System.Timers.ElapsedEventHandler(runTime_Elapsed);
this.runTime.Start();
}
}
void runTime_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.runTime.Stop();
this.Stop();
this.IsRunning = false;
}
public void Start()
{
this.IsRunning = true;
Random r = new Random(DateTime.Now.Millisecond);
for (int i = 0; i < this.NumberOfThreads; i++)
{
string threadPoolId = Math.Ceiling(r.NextDouble() * 10).ToString();
Worker worker = new Worker("-" + threadPoolId); //i.ToString());
worker.Sleep = this.Sleep;
this.Workers.Add(worker);
Thread thread = new Thread(worker.Work);
worker.Name = string.Format("WorkerThread-{0}", i);
thread.Name = worker.Name;
this.Threads.Add(thread);
thread.Start();
Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "Started new Worker Thread. Total active: {0}", i + 1));
}
}
public void Stop()
{
if (this.Workers != null)
{
lock (lockVar)
{
for (int i = 0; i < this.Workers.Count; i++)
{
//Thread thread = this.Threads[i];
//thread.Interrupt();
this.Workers[i].IsEnabled = false;
}
for (int i = this.Workers.Count - 1; i >= 0; i--)
{
Worker worker = this.Workers[i];
while (worker.IsRunning)
{
Thread.Sleep(32);
}
}
foreach (Thread thread in this.Threads)
{
thread.Abort();
}
this.Workers.Clear();
this.Threads.Clear();
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Threading;
using System.ComponentModel;
using System.Data.OleDb;
namespace ThreadAndSQLTester
{
class Worker
{
public bool IsEnabled { get; set; }
public bool IsRunning { get; set; }
public string Name { get; set; }
public int Sleep { get; set; }
private string dataCnString { get; set; }
private string logCnString { get; set; }
private List<Log> Logs { get; set; }
public Worker(string threadPoolId)
{
this.Logs = new List<Log>();
SqlConnectionStringBuilder cnBldr = new SqlConnectionStringBuilder();
cnBldr.DataSource = #"trgcrmqa3";
cnBldr.InitialCatalog = "Scratch";
cnBldr.IntegratedSecurity = true;
cnBldr.MultipleActiveResultSets = true;
cnBldr.Pooling = true;
dataCnString = GetConnectionStringWithWorkStationId(cnBldr.ToString(), threadPoolId);
cnBldr = new SqlConnectionStringBuilder();
cnBldr.DataSource = #"trgcrmqa3";
cnBldr.InitialCatalog = "Scratch";
cnBldr.IntegratedSecurity = true;
logCnString = GetConnectionStringWithWorkStationId(cnBldr.ToString(), string.Empty);
IsEnabled = true;
}
private string machineName { get; set; }
private string GetConnectionStringWithWorkStationId(string connectionString, string connectionPoolToken)
{
if (string.IsNullOrEmpty(machineName)) machineName = Environment.MachineName;
SqlConnectionStringBuilder cnbdlr;
try
{
cnbdlr = new SqlConnectionStringBuilder(connectionString);
}
catch
{
throw new ArgumentException("connection string was an invalid format");
}
cnbdlr.WorkstationID = machineName + connectionPoolToken;
return cnbdlr.ConnectionString;
}
public void Work()
{
int i = 0;
while (this.IsEnabled)
{
this.IsRunning = true;
try
{
Log log = new Log();
log.WorkItemId = Guid.NewGuid();
log.StartTime = DateTime.Now;
List<object> lst = new List<object>();
using (SqlConnection cn = new SqlConnection(this.dataCnString))
{
try
{
cn.Open();
using (SqlCommand cmd = new SqlCommand("Analysis.spSelectTestData", cn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) // DBHelper.ExecuteReader(cn, cmd))
{
while (dr.Read())
{
CreateClaimHeader2(dr, lst);
}
dr.Close();
}
cmd.Cancel();
}
}
catch { }
finally
{
cn.Close();
}
}
log.StopTime = DateTime.Now;
log.RouteName = this.Name;
log.HostName = this.machineName;
this.Logs.Add(log);
i++;
if (i > 1000)
{
Console.WriteLine(string.Format("Thread: {0} executed {1} items.", this.Name, i));
i = 0;
}
if (this.Sleep > 0) Thread.Sleep(this.Sleep);
}
catch { }
}
this.LogMessages();
this.IsRunning = false;
}
private void CreateClaimHeader2(IDataReader reader, List<object> lst)
{
lst.Add(reader["ClaimHeaderID"]);
lst.Add(reader["ClientCode"]);
lst.Add(reader["MemberID"]);
lst.Add(reader["ProviderID"]);
lst.Add(reader["ClaimNumber"]);
lst.Add(reader["PatientAcctNumber"]);
lst.Add(reader["Source"]);
lst.Add(reader["SourceID"]);
lst.Add(reader["TotalPayAmount"]);
lst.Add(reader["TotalBillAmount"]);
lst.Add(reader["FirstDateOfService"]);
lst.Add(reader["LastDateOfService"]);
lst.Add(reader["MaxStartDateOfService"]);
lst.Add(reader["MaxValidStartDateOfService"]);
lst.Add(reader["LastUpdated"]);
lst.Add(reader["UpdatedBy"]);
}
/// <summary>
/// Toes the data table.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data">The data.</param>
/// <returns></returns>
public DataTable ToDataTable<T>(IEnumerable<T> data)
{
PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(typeof(T));
if (props == null) throw new ArgumentNullException("Table properties.");
if (data == null) throw new ArgumentNullException("data");
DataTable table = new DataTable();
for (int i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
}
object[] values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = props[i].GetValue(item) ?? DBNull.Value;
}
table.Rows.Add(values);
}
return table;
}
private void LogMessages()
{
using (SqlConnection cn = new SqlConnection(this.logCnString))
{
try
{
cn.Open();
DataTable dt = ToDataTable(this.Logs);
Console.WriteLine(string.Format("Logging {0} records for Thread: {1}", this.Logs.Count, this.Name));
using (SqlCommand cmd = new SqlCommand("Analysis.spInsertWorkItemRouteLog", cn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#dt", dt);
cmd.ExecuteNonQuery();
}
Console.WriteLine(string.Format("Logged {0} records for Thread: {1}", this.Logs.Count, this.Name));
}
finally
{
cn.Close();
}
}
}
}
}
1.A DataReader works in a connected environment,
whereas DataSet works in a disconnected environment.
2.A DataSet represents an in-memory cache of data consisting of any number of inter related DataTable objects. A DataTable object represents a tabular block of in-memory data.
SqlDataAdapter or sqlDataReader
Difference between SqlDataAdapter or sqlDataReader ?
Ans : 1.A DataReader works in a connected environment,
whereas DataSet works in a disconnected environment.
2.A DataSet represents an in-memory cache of data consisting of any number of inter related DataTable objects. A DataTable object represents a tabular block of in-memory data.
SqlDataAdapter or sqlDataReader